代码之家  ›  专栏  ›  技术社区  ›  Brian Sweeney

在C中的sqlite数据库上运行并发插入时遇到困难#

  •  4
  • Brian Sweeney  · 技术社区  · 16 年前

    我正在运行多个线程,每个线程都试图对一个sqlite数据库执行插入操作。每个线程都创建自己与数据库的连接。它们各自创建一个命令,打开一个事务,执行一些插入,然后关闭该事务。似乎尝试任何操作的第二个线程得到以下sqliteException:数据库文件被锁定。我尝试从事务中解包插入,并缩小每个提交中包含的插入的范围,但没有实际效果;随后对db文件的访问会引发相同的异常。

    有什么想法吗?我被难住了,不知道下一步该去哪里……

    3 回复  |  直到 14 年前
        1
  •  5
  •   John Millikin    16 年前

    更新插入代码,以便当它遇到指示数据库锁的异常时,它会稍等片刻,然后重试。每次随机增加等待时间(“随机退避”算法)。这应该允许线程每次获取全局写锁。性能将很差,但代码应该在不进行重大修改的情况下工作。

    但是,sqlite不适用于高度并发的修改。您有两个永久解决方案:

    • 移动到“真实”数据库,如PostgreSQL或MySQL
    • 通过一个线程序列化所有数据库修改,以避免sqlite的修改。
        2
  •  1
  •   Noah    16 年前

    有两件事要检查:

    1)确认您的sqlite版本是使用线程支持编译的

    2)确认您没有以独占方式打开数据库

        3
  •  0
  •   ubzack    14 年前

    我不是在C中执行此操作,而是在Android中执行此操作,但我通过在包装类的整个生命周期内保持SQLite数据库始终在拥有它的包装类中打开来绕过此“数据库被锁定”错误。在这个类中完成的每个插入都可以在自己的线程中(因为,根据您的数据存储情况、SD卡和设备内存等,DB写入可能需要很长时间),我甚至尝试限制它,一次生成大约12个插入线程,并且每个线程都处理得很好,因为insert方法不必担心ab向外打开/关闭数据库。

    不过,我不确定持久的DB生命周期是否被认为是好的样式(在大多数情况下,它可能被认为是坏的),但目前它工作得很好。

    推荐文章