我在C ++中有一段代码可以创建许多线程&这些线程中的每一个都访问一个共同的SQLite数据库&选择&插入数据。
所有INSERT都在事务中。很多次我收到“数据库被锁定”错误。
我该如何解决这个问题?
答案 0 :(得分:7)
您可以以多线程方式使用SQLite,但是对于每个线程,您必须打开一个新连接(sqlite3_open()
)并对该连接进行操作。< / p>
答案 1 :(得分:2)
如果你在多个线程上只用“BEGIN”开始你的事务而你正在使用INSERT,那么sqlite就会死锁。
那是因为sqlite只获取BEGIN上的读锁定。在INSERT上,它必须将读锁定升级到写锁定(只有在没有读锁定时才能执行)。 对于journal_mode = WAL(仅默认的journal_mode = delete),这不会发生,因为wal模式允许在写入期间进行读取访问。 (因此使用WAL模式可能是一个修复)。
解决方案: 如果您计划在事务中使用插入,请使用BEGIN IMMEDIATE。这样sqlite就会在数据库上获取写锁定。
答案 2 :(得分:0)
我主要是试图指出,正如一些人所假设的那样,你不应该有多个用户写入同一个SQLite DB,因为这不是它的设计目的;
(5)可以多个应用程序或多个实例相同 应用程序同时访问单个数据库文件?
多个进程可以同时打开同一个数据库。 多个进程可以同时执行SELECT。但是只有 一个进程可以随时对数据库进行更改 然而,时间。
SQLite使用读取器/写入器锁来控制对数据库的访问。 (在Win95 / 98 / ME下,缺少对读写器锁的支持,a 改为使用概率模拟。)但要谨慎:这个 如果数据库文件是,锁定机制可能无法正常工作 保存在NFS文件系统上。这是因为fcntl()文件锁定是 在许多NFS实现上打破了。你应该避免使用SQLite NFS上的数据库文件,如果多个进程可能尝试访问 同时提交文件。在Windows上,微软的文档说明了这一点 如果您没有运行,则锁定在FAT文件系统下可能无法正常工作 Share.exe守护程序。对Windows有很多经验的人 告诉我,网络文件的文件锁定是非常错误的,而不是 可信。如果他们说的是真的,那就共享一个SQLite数据库 两台或多台Windows机器之间可能会出现意外问题。
我们知道没有其他支持as的嵌入式SQL数据库引擎 和SQLite一样多并发。 SQLite允许多个进程拥有 数据库文件立即打开,并为多个进程读取 数据库一下子。当任何进程想要写入时,它必须锁定 整个数据库文件的更新期间。但通常情况下 只需几毫秒。其他进程只是等待作者 完成然后继续他们的业务。其他嵌入式SQL 数据库引擎通常只允许单个进程连接 数据库一下子。
但是,客户端/服务器数据库引擎(例如PostgreSQL,MySQL或 Oracle)通常支持更高级别的并发和允许 多个进程要同时写入同一个数据库 时间。这在客户端/服务器数据库中是可能的,因为存在 始终是一个可以协调的良好控制的服务器进程 访问。如果您的应用程序需要大量并发,那么 您应该考虑使用客户端/服务器数据库。但经验 表明大多数应用程序需要的并发性要比它们少得多 设计师想象。
当SQLite尝试访问被另一个进程锁定的文件时, 默认行为是返回SQLITE_BUSY。你可以调整它 来自C代码的行为 使用sqlite3_busy_handler()或sqlite3_busy_timeout()API函数。