2011-08-19 164 views
3

我有一段C++中的代码,它创建了很多线程&这些线程中的每一个都访问一个常见的SQLite数据库& SELECTs & INSERTs data。SQLite数据库被锁定

所有INSERT都处于事务中。很多时候,我收到“数据库已锁定”错误。

我该如何解决这个问题?

回答

7

可以使用SQLite在多线程的方式,但对于每一个线程,你必须打开一个新的连接(sqlite3_open())和连接上的操作。

有一个在official documentation

+0

很棒!谢谢! – omggs

0

我主要试图指出,正如一些人认为的,你不应该让多个用户写入相同的SQLite数据库,因为这不是它的设计目的;

(5)多个应用程序或同一个应用程序的多个实例可以同时访问单个数据库文件吗?

多个进程可以同时打开同一个数据库。 多个进程可以同时做一个SELECT。但是,只有 一个进程可以在 的任何时刻对数据库进行更改。

SQLite使用读写器锁来控制对数据库的访问。 (在Win95/98/ME中,缺少对读写器锁定的支持,而是使用概率模拟代替 )。但请注意:如果数据库文件保留在NFS文件系统上,则此锁定机制可能无法正常工作。这是因为fcntl()文件锁定在许多NFS实现上破坏了 。如果多个进程可能尝试同时访问 文件,则应避免将SQLite 数据库文件放在NFS上。在Windows上,Microsoft的文档说如果您没有运行 Share.exe守护进程, 锁定可能无法在FAT文件系统下工作。对Windows 有很多经验的人告诉我,网络文件的文件锁定非常麻烦,并且不是 可靠的。如果他们说的是真的,在两台或多台Windows机器之间共享SQLite数据库 可能会导致意外问题。

我们意识到没有其他嵌入式SQL数据库引擎可以像SQLite那样支持很多并发性,如 。 SQLite允许多个进程一次打开数据库文件,并允许多个进程一次读取数据库 。当任何进程想要写入时,它必须在整个数据库文件更新期间锁定整个数据库文件。但通常 只需要几毫秒。其他进程只需等待作者 完成,然后继续他们的业务。其他嵌入式SQL数据库引擎通常只允许单个进程一次连接到数据库。

然而,客户机/服务器数据库引擎(如PostgreSQL的,MySQL和或 甲骨文)通常支持并发的更高水平,并允许 多个进程在同一 时间被写入到相同的数据库。这在客户端/服务器数据库中是可能的,因为总是有一个良好控制的服务器进程可用来协调 访问。如果您的应用程序需要很多并发性,那么您应该考虑使用客户机/服务器数据库。但是经验 表明,大多数应用程序所需要的并发性比设计者想象的要少得多。

当SQLite试图访问被另一进程锁定的文件时, 的默认行为是返回SQLITE_BUSY。您可以使用sqlite3_busy_handler()或sqlite3_busy_timeout()API函数从C代码 调整这个 行为。

来源:http://www.sqlite.org/faq.html

+1

假的,它使用多线程/ multiconnection。请参阅http://www.sqlite.org/threadsafe.html –

+0

我更新了,对不起 – Coops

2

更多信息。如果你开始你的交易只对一个多线程的“开始”,然后您正在使用的INSERT源码可以死锁。

这是因为只有源码上aquires开始读锁。在INSERT上,它必须将读锁升级到写锁(只有在没有读锁的情况下才能执行)。 随着wal模式在写入期间允许读取访问,journal_mode = WAL(仅默认journal_mode = delete)时不会发生这种情况。 (所以使用WAL模式可能是一个解决方法)。

解决方案:使用 立刻开始,如果你打算在交易中使用的刀片。这样sqlite获得数据库的写入锁定。