当我在读取数据库的同时调用数据库写入时,SQLite 在我的机器中抛出一个扳手时遇到了麻烦。当不同的方法碰巧同时尝试访问数据库时,就会发生这种情况。


我正在做的类似于这个线程中正在做的事情,接受的答案解释了如何使用数据库事务来避免数据库锁定。


这是我的一些代码:


stmt, err := dbtx.Prepare(`statement`)

if err != nil {

    log.Fatal(err)

}


_, err = stmt.Exec(values, values, values)

if err != nil {        

    log.Fatal(err)

}


err = dbtx.Commit()

if err != nil {

    fmt.Println("database lock?")

    fmt.Println(err)

    dbtx.Rollback()

}


fmt.Println("Database storage complete!")

令人困惑的是程序在输出后存在:


database lock?

database is locked

Database storage complete!

2014/09/09 18:33:11 database is locked

exit status 1

我不希望我的程序因数据库锁定而停止,我希望它将数据存储在内存中并继续其业务,直到数据库解锁,我可以再试一次。


是否有一些标准的方法可以实现这一点,也许是某种队列或数据结构,或者是否有特定于数据库的方法来解决这个问题?


为什么程序输出后退出Database storage complete!?



我相信我已经解决了这个问题,但我不能确定。我正在使用 goroutines 和包范围的数据库连接。以前,我的代码中的每个 func 在被调用时都会初始化一个数据库连接。现在,我在包的顶部定义了一个用于 DB 连接的“全局”变量,并在任何例程开始之前进行了初始化。简而言之,代码如下:


var nDB *sql.DB

稍后在主函数中...


mypkg.InitDB()

go mypkg.RunDatabaseOperations()

mypkg.BeginHTTPWatcher(rtr)

InitDB() 定义如下:


func InitDB() {

    fmt.Println("Init DB ...")

    var err error

    nDB, err = sql.Open("sqlite3", "./first.db")

    if err != nil {

        log.Fatal(err)

    }

    if nDB == nil {

        log.Fatal(err)

    }

    fmt.Printf("nDB: %v\n", ODB)

    fmt.Println("testing db connection...")

    err2 := nDB.Ping()

    if err2 != nil {

        log.Fatalf("Error on opening database connection: %s", err2.Error())

    }

}

因此,RunDatabaseOperations定期扫描在线资源中的数据,并在发生更改时将其存储到数据库中(每隔几秒一次)。BeginHTTPWatcher侦听 HTTP 请求,因此可以从正在运行的程序中读取数据,并通过网络将数据传输到数据的请求者,无论是本地请求还是外部请求。我还没有遇到问题。