SQLite多进程访问

我们在多进程和multithreading应用程序中使用SQLite。 SQLite数据库文件使用嵌入式SQLite加密进行加密。 FAQ说明SQLite应该能够使用锁机制管理多进程访问。 我们遇到了一个奇怪的问题:当许multithreading访问同一个数据库文件时,有时会发生约束违规,更具体地说 – 具有唯一约束的字段在调用“insert或replace”语句后获得重复值。 它现在经常发生,我们正在使用加密。 在我们开始使用SQLite加密之前,我们没有注意到这种行为。 这有什么具体的已知问题吗?

虽然SQLite是“线程安全的”,但您仍然无法同时修改数据库:

然后每个线程继续插入一些记录,假设为1000.您将遇到的问题如下:一个线程将通过设置对文件的锁定来控制数据库。 这很好,但是当锁定处于活动状态时,其余的线程将在每个尝试的INSERT中继续失败。 ( 参考 )

一次只允许一个线程修改数据库,但是您可以有多个线程尝试修改数据库。

如果要避免失败时锁定问题,可以检查SQLITE_BUSY标志:

测试SQLITE_BUSY,我最初没有这样做。 这里有一些伪代码来说明解决方案:

while (continueTrying) { retval = sqlite_exec(db, sqlQuery, callback, 0, &msg); switch (retval) { case SQLITE_BUSY: Log("[%s] SQLITE_BUSY: sleeping fow a while...", threadName); sleep a bit... (use something like sleep(), for example) break; case SQLITE_OK: continueTrying = NO; // We're done break; default: Log("[%s] Can't execute \"%s\": %s\n", threadName, sqlQuery, msg); continueTrying = NO; break; } } return retval; 

相同的参考

我敢打赌,你的约束违规与multithreading无关,所以请你发布你得到的实际约束违规(或者一个符合www.sscce.org的例子)。

谢谢你们的评论!

(提到我们正在使用System.Data.SQLite .Net库)

与此同时,我们进行了更多测试,结果如下

===============

我们构建了一个执行以下操作的测试器: – 创建一个包含许多字段的表。 其中一个字段–nvarchar(255) – 具有唯一索引:“在表上创建唯一索引IX_MyKey(MyKey)” – 同时启动许多标识进程(25) – 每个进程都有一个Key(表示数字1-25的字符串) – 每个进程都有一个(主)线程在循环中执行以下操作30秒:

读取记录,其中MyKey = @MyKey(进程的密钥)获取一个数字字段的值,将’value + 1’写回同一记录的相同字段“insert或replace … where MyKey = @ MyKey”

===============

  • 当我们使用没有加密的System.Data.SQLite库完成上述操作时 – 一切都按预期工作(包括在进程数量增加时减慢对数据库的访问的锁)

  • 当我们使用加密(通过为数据库设置密码)时,索引唯一约束被“破坏” – 出现具有相同MyKey值的记录

===============

所以接缝问题与加密有某种关系……

确保你没有跨线程共享连接 – 每个线程应该使它自己的连接。 并确保将查询包装在事务中。

我使用开源的System.Data.Sqlite( http://sqlite.phxsoftware.com/ )ADO.Net包装器,只要您不跨线程共享连接,它就是线程安全的。 它还可以轻松加密数据库,如下所述: http : //sqlite.phxsoftware.com/forums/t/130.aspx (只需设置密码属性)。 在他的论坛中搜索他如何专门使用Microsoft Crypto API进行加密,以及有关线程安全的详细信息。