2010-05-05 195 views
7

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

+0

SQLite声明,您不能在线程之间共享相同的对象。你确定你不这样做吗? – Andrey 2010-05-05 18:03:39

+0

@Andrey:你可以发布这个链接吗?当我最近阅读它时,SQLite说它是线程安全的,尽管*他们认为线程是邪恶的,并且你不应该在多线程程序中使用SQLite,除非它只能被一个线程访问。但从技术上讲,它应该是线程安全的。至少,这是我所记得的。 – Dave 2010-05-05 18:28:49

+0

@Dave:http://www.sqlite.org/cvstrac/wiki?p=MultiThreading关键短语:通过“线程安全”,我们的意思是您可以同时在不同的线程中使用不同的SQLite数据库连接。 – Andrey 2010-05-05 18:34:13

回答

8

虽然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; 

same reference

我敢打赌,你的约束违反无关多线程,所以你可以请张贴实际的约束冲突,你(或符合www.sscce.org的示例)。

0

确保你没有跨线程共享连接 - 每个线程都应该建立自己的连接。并确保你在交易中包装你的查询。

我使用开源的System.Data.Sqlite(http://sqlite.phxsoftware.com/)ADO.Net包装器,只要您不共享线程间的连接,它就是线程安全的。它也很容易加密数据库,如下所述:http://sqlite.phxsoftware.com/forums/t/130.aspx(只需设置密码属性)。搜索他的论坛,了解他如何特别使用Microsoft Crypto API来执行加密,以及有关线程安全性的详细信息。

2

感谢您的所有意见!

(这是要提到我们正在使用System.Data.SQLite。网库)

在此期间我们做了一些测试,这里是

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

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

读取的记录,其中的myKey = @的myKey(该过程的密钥) 得到的一个值数字字段 向同一记录的相同字段回写'值+ 1'插入或替换...其中MyKey = @ MyKey“

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

  • 当我们做上述所有使用System.Data.SQLite库没有加密 - 一切正常(包括正在放缓锁的访问时的处理的量增加数据库中)

  • 当我们使用加密(用密码设定到数据库),索引唯一约束是“破” - 那里出现具有相同的myKey值

  • 记录

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

因此,它接缝的问题是以某种方式与加密有关...