Maison > développement back-end > Golang > le corps du texte

Erreur de table intermittente manquante dans SQLite : Mémoire : Base de données

WBOY
Libérer: 2024-02-09 20:24:09
avant
895 Les gens l'ont consulté

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

l'éditeur php Banana vous apporte une solution à l'erreur de perte de table intermittente dans SQLite. Lorsque nous utilisons une base de données SQLite, nous pouvons rencontrer des erreurs de mémoire ou des pertes de tables. Cette erreur est généralement provoquée par des opérations de base de données incorrectes ou des problèmes de mémoire. Afin de résoudre ce problème, nous pouvons prendre certaines mesures, telles que l'optimisation des instructions de requête, l'augmentation des limites de mémoire, etc. Dans cet article, nous détaillerons comment dépanner et résoudre ce problème pour garantir le bon fonctionnement de la base de données.

Contenu de la question

Nous utilisons SQLite 3.39.4 dans Go via github.com/mattn/go-sqlite3 v1.14.16. La chaîne de connexion est ":memory:?cache=shared&mode=rwc&_mutex=no&_journal=WAL&_sync=NORMAL"

Nous voyons occasionnellement l'erreur « No such table: configuration » dans nos tests. Ce qui est déroutant, c'est que la requête en question a été utilisée avec succès dans le scénario de test et que la table apparaît ensuite dans les requêtes adressées à sqlite_master , à la fois dans la connexion à la base de données et dans l'objet de transaction qui génère l'erreur. Cependant, dès qu’une erreur se produit, la requête n’aboutit plus.

Je me rends compte que c'est une question plutôt vague, mais quelqu'un peut-il au moins suggérer où chercher ? Les connexions à la base de données ont toujours la même valeur de pointeur.

Mise à jour :

Lors de mon deuxième essai, j'ai presquepourrais reproduire le problème dans ce SSCCE :

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)
    }
}
Copier après la connexion

C'est différent du problème réel car showTables n'affiche pas les tables dans SSCCE mais c'est le cas dans le test réel. Cet exemple montre le problème de l'utilisation de :memory: au lieu de example.db, mais uniquement si la transaction n'est pas fermée. Est-ce un comportement connu ou attendu des bases de données en mémoire ? :memory: 而不是 example.db 的问题,但前提是事务未关闭。这是内存数据库已知的或预期的行为吗?

解决方法

Go database/sql 隐式使用连接池,但 :memory:Solution de contournementGo database/sql utilise implicitement le regroupement de connexions, mais les bases de données :memory: ouvrent leurs connexions en privé

par défaut. Veuillez vous référer à :

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

cache=shared,正如您所尝试的那样。但 SQLite 要求将其指定为 URI:file::memory:?cache=sharedfile:Étant donné que plusieurs connexions SQLite sont créées/fermées en coulisses, vous ne savez pas vraiment quelle connexion exécute chaque instruction et sur quelle base de données, donc naturellement certaines connexions peuvent voir certaines données et d'autres ne peuvent pas arriver.

Une façon de partager une connexion est d'utiliser

est important).
  • Un moyen plus fiable d'ouvrir une base de données à mémoire partagée est : file:memdb1?mode=memory&cache=shared(命名为 memdb1
  • file:/memdb1?vfs=memdb(命名为 /memdb1,并使用 memdb)

VFS)

🎜 🎜 Vos autres paramètres peuvent être inutiles voire nuisibles (pour les bases de données en mémoire). 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!