golang sqlite数据库连接池

时间:2014-09-09 19:01:39

标签: database sqlite error-handling go

当我在与读取相同的时间调用数据库时,SQLite在我的机器中抛出扳手时遇到了麻烦。当不同的方法试图在同一时间访问数据库时会发生这种情况。

我所做的与this thread中所做的类似,接受的答案解释了如何使用数据库事务来避免数据库锁定。

以下是我的一些代码:

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!后程序会退出?

修改

我相信我已经解决了这个问题,但我无法确定。我正在使用goroutine和一个程序包范围的数据库连接。以前,我的代码中的每个函数都在调用时初始化数据库连接。现在,我有一个"全球"包的顶部定义的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请求,以便可以从正在运行的程序中读取数据,并通过线程将数据传输到数据的请求者,无论是本地请求还是外部请求。我还没有遇到问题。

2 个答案:

答案 0 :(得分:7)

documentation说:

  

单个连接实例及其所有派生对象(预处理语句,备份操作等)可能无法在没有外部同步的情况下从多个goroutine中同时使用。

(这是一个不同的SQLite驱动程序,但此限制也适用于您的。)

当您使用goroutine时,必须使用单独的数据库连接。

默认情况下,SQLite在遇到另一个事务锁定的数据库时立即中止。 为了允许更多的并发性,您可以通过设置繁忙超时来告诉它等待另一个事务完成。

如果您的SQLite驱动程序有,请使用BusyTimeout函数,或直接执行PRAGMA busy_timeout SQL命令。

答案 1 :(得分:0)

请发布更多代码,以便我们更全面地了解正在发生的事情。

然而,这里有几点想法。默认情况下Golang池数据库连接(尽管,CENTOS似乎不是......)。此外,您的程序正在“暂停”,因为它正在等待来自数据库连接池的打开连接。如果您希望程序的其余部分在此期间继续,则应将其作为异步函数运行 - 请查看goroutines here。这将有效地使您的程序按照您的意愿排队,因为连接将按照它们可用时请求的顺序进行分配。 Read more over here如果您对内部感兴趣。

如果您需要一些关于goroutine外观的代码段,请告诉我们。