Heim  >  Artikel  >  Backend-Entwicklung  >  Zeitweiliger Fehler wegen fehlender Tabelle in SQLite: Speicher: Datenbank

Zeitweiliger Fehler wegen fehlender Tabelle in SQLite: Speicher: Datenbank

WBOY
WBOYnach vorne
2024-02-09 20:24:09898Durchsuche

SQLite 中间歇性表丢失错误:内存:数据库

Der PHP-Editor Banana bietet Ihnen eine Lösung für den zeitweiligen Tabellenverlustfehler in SQLite. Wenn wir eine SQLite-Datenbank verwenden, kann es zu Speicherfehlern oder Tabellenverlusten kommen. Dieser Fehler wird normalerweise durch fehlerhafte Datenbankoperationen oder Speicherprobleme verursacht. Um dieses Problem zu lösen, können wir einige Maßnahmen ergreifen, z. B. die Optimierung von Abfrageanweisungen, die Erhöhung der Speichergrenzen usw. In diesem Artikel beschreiben wir detailliert, wie Sie dieses Problem beheben und beheben können, um einen ordnungsgemäßen Datenbankbetrieb sicherzustellen.

Frageninhalt

Wir verwenden SQLite 3.39.4 in Go über github.com/mattn/go-sqlite3 v1.14.16. Die Verbindungszeichenfolge ist ":memory:?cache=shared&mode=rwc&_mutex=no&_journal=WAL&_sync=NORMAL"

In unseren Tests sehen wir gelegentlich den Fehler „Keine solche Tabelle: Konfiguration“. Was verwirrend ist, ist, dass die betreffende Abfrage im Testfall erfolgreich verwendet wurde und die Tabelle anschließend in Abfragen an sqlite_master angezeigt wird, sowohl in der Datenbankverbindung als auch im Transaktionsobjekt, das den Fehler auslöst. Sobald jedoch ein Fehler auftritt, ist die Abfrage nicht mehr erfolgreich.

Mir ist klar, dass dies eine ziemlich vage Frage ist, aber kann jemand zumindest vorschlagen, wo man suchen muss? Datenbankverbindungen haben immer den gleichen Zeigerwert.

Update:

Bei meinem zweiten Versuch konnte ich das Problem in diesem SSCCE fastreproduzieren:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/mattn/go-sqlite3"
    "os"
)

func main() {
    os.Remove("example.db")
    db, err := sql.Open("sqlite3", ":memory:")
    if err != nil {
        panic(err)
    }

    for _, s := range []string{
        "CREATE TABLE if not exists Configuration (" +
            "`id` varchar(1024) NOT NULL," +
            "`body` varchar(10240) DEFAULT NULL, " +
            "PRIMARY KEY (id) " +
            ")",
        "INSERT INTO Configuration (id, body) VALUES ('some-unique-value', 'another-unique-value')",
    } {
        _, err = db.Exec(s)
        if err != nil {
            panic(err)
        }
    }

    for i := 0; i < 10; i++ {
        tx, err := db.Begin()
        if err != nil {
            panic(err)
        }

        q, err := tx.Prepare("select Configuration.id, Configuration.body \n\t\t\tfrom Configuration\n\t\t\tWHERE Configuration.id = ? ")
        fmt.Println(i, err)
        if q != nil {
            _ = q.Close()
        }

        fmt.Println("tx:")
        showTables(tx)

        fmt.Println("db:")
        showTables(db)

        tx.Commit()
    }
}

func showTables(db interface {
    Query(query string, args ...interface{}) (*sql.Rows, error)
}) {
    r, err := db.Query("SELECT name FROM sqlite_master")
    if err != nil {
        panic(err)
    }
    for r.Next() {
        var name string
        _ = r.Scan(&name)
        fmt.Println(name)
    }
}

Es unterscheidet sich von der eigentlichen Frage, da showTables die Tabellen nicht in SSCCE anzeigt, sondern im eigentlichen Test. Dieses Beispiel zeigt das Problem der Verwendung von :memory: anstelle von example.db, jedoch nur, wenn die Transaktion nicht geschlossen ist. Ist dies ein bekanntes oder erwartetes Verhalten von In-Memory-Datenbanken? :memory: 而不是 example.db 的问题,但前提是事务未关闭。这是内存数据库已知的或预期的行为吗?

解决方法

Go database/sql 隐式使用连接池,但 :memory:WorkaroundGo database/sql verwendet implizit Verbindungspooling, aber :memory: Datenbanken öffnen ihre Verbindungen standardmäßig privat

. Bitte beachten Sie:

https://www.php.cn/link/d346256ad566cf97801e5cecc45a2557

cache=shared,正如您所尝试的那样。但 SQLite 要求将其指定为 URI:file::memory:?cache=sharedfile:Da hinter den Kulissen mehrere SQLite-Verbindungen erstellt/geschlossen werden, wissen Sie nicht wirklich, welche Verbindung welche Anweisung und für welche Datenbank ausführt, sodass einige Verbindungen natürlich bestimmte Daten sehen können und andere nicht ankommen können.

Eine Möglichkeit, eine Verbindung zu teilen, ist die Verwendung von

ist wichtig).
  • Eine zuverlässigere Möglichkeit, eine Shared-Memory-Datenbank zu öffnen, ist: file:memdb1?mode=memory&cache=shared(命名为 memdb1
  • file:/memdb1?vfs=memdb(命名为 /memdb1,并使用 memdb)

VFS)

🎜 🎜 Ihre anderen Parameter können unnötig oder sogar schädlich sein (für In-Memory-Datenbanken). 🎜

Das obige ist der detaillierte Inhalt vonZeitweiliger Fehler wegen fehlender Tabelle in SQLite: Speicher: Datenbank. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen