我们在多进程和多线程应用程序中使用SQLite。 SQLite数据库文件使用嵌入式SQLite加密进行加密。 FAQ表示SQLite应该能够使用锁机制管理多进程访问。 我们遇到了一个奇怪的问题: 当许多线程访问同一个数据库文件时,有时会发生约束违规,更具体地说 - 具有唯一约束的字段在调用“insert或replace”语句后获得重复值。 它现在经常发生,我们正在使用加密。在我们开始使用SQLite加密之前,我们没有注意到这种行为。 这有什么具体的已知问题吗?
答案 0 :(得分:9)
虽然SQLite是“线程安全的”,但您仍然无法同时修改数据库:
然后每个线程继续插入一个 记录数量,比方说1000 你会遇到的问题是 以下:一个线程将获得控制权 通过设置锁定在数据库上 文件。这很好,但其余的 线程将继续失败 对于每次尝试INSERT而 锁是活跃的。 (reference)
一次只允许一个线程修改数据库,但是您可以有多个尝试的线程来修改数据库。
如果您想避免失败时锁定问题,可以检查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;
我敢打赌,你的约束违规与多线程无关,所以请你发布你得到的实际约束违规(或者符合www.sscce.org的例子)。
答案 1 :(得分:2)
感谢您的所有评论!
(提到我们正在使用System.Data.SQLite .Net库)
与此同时,我们进行了一些测试,结果是
===============
我们已经构建了一个执行以下操作的测试器: - 创建一个包含许多字段的表。其中一个字段--nvarchar(255) - 具有唯一索引:“在表上创建唯一索引IX_MyKey(MyKey)” - 同时启动许多识别过程(25) - 每个进程都有一个Key(字符串代表1-25) - 每个进程都有一个(主)线程在循环中执行以下操作30秒:
读取MyKey = @ MyKey的记录(过程的关键) 获取数字字段的值 将'value + 1'写回同一记录的同一字段“insert or replace ... where MyKey = @ MyKey”
===============
当我们使用没有加密的System.Data.SQLite库完成上述操作时 - 一切都按预期工作(包括在进程数量增加时减慢对数据库的访问的锁)
< / LI>当我们使用加密(通过设置数据库的密码)时,索引唯一约束被“破坏” - 出现具有相同MyKey值的记录
===============
因此接缝问题与加密有某种关系......
答案 2 :(得分:0)
确保您没有跨线程共享连接 - 每个线程都应该建立自己的连接。并确保将查询包装在事务中。
我使用开源的System.Data.Sqlite(http://sqlite.phxsoftware.com/)ADO.Net包装器,只要您不跨线程共享连接,它就是线程安全的。它也很容易加密数据库,如下所述:http://sqlite.phxsoftware.com/forums/t/130.aspx(只需设置密码属性)。在他的论坛中搜索他如何专门使用Microsoft Crypto API进行加密,以及有关线程安全的详细信息。