gpt4 book ai didi

database - SQLite3 的线程安全性如何?

转载 作者:搜寻专家 更新时间:2023-10-30 19:55:56 24 4
gpt4 key购买 nike

我对 SQLite3 中的多线程有疑问。在我的场景中,我有几个进程想要写入同一个 SQLite3 数据库。

manual , 它说

Multi-thread. In this mode, SQLite can be safely used by multiple threads provided that no single database connection is used simultaneously in two or more threads.

我写了一个示例程序,其中有几个(比如 10 个)线程使用相同的数据库连接插入到相同数据库的相同表中。

CREATE TABLE IF NOT EXISTS StatusTable (ID INTEGER PRIMARY KEY, Thread TEXT NOT NULL, Module TEXT NOT NULL, Status INTEGER NOT NULL);

插入是

sprintf(acBuffer, "INSERT INTO StatusTable(Thread, Module, Status) VALUES('%s', 'testnumber%d', %d);", acThread, i, thisThread);

其中acThread是包含进程ID和线程ID的字符串,i从1到100,thisThread是线程ID。线程在 while 循环中执行 100 次 INSERT,然后退出。

根据上面的说法,虽然我看不出有什么问题,但这并不安全。

  1. 使用 10 个线程和一个共享的 sqlite3 对象,每个线程插入 100 行:没有插入丢失,也没有发生超时。
  2. 使用 10 个线程,每个线程都有一个单独的 sqlite3 对象,每个线程插入 100 行:一些插入不成功(大约 0.5 到 1%),因为数据库被锁定。
  3. 使用case 1的两个过程:和case 2一样,有一些损失(大约0.1%)。

我正在使用 PRAGMA journal_mode=WAL;PRAGMA busy_timeout=10000;

现在我的问题:

  • 我真的不应该在线程之间共享连接对象吗?如果我这样做会发生什么坏事?
  • 为什么第一种情况(使用共享数据库连接)有效(所有插入都成功,没有超时)?我需要做什么才能“破坏”SQLite?那么会发生什么?
  • 我假设每个线程都应该有自己的连接。如何避免插入失败?在我的例子中,只有插入,没有读者。高得离谱的 busy_timeout(10 秒)没有按预期工作,仍然出现“数据库被锁定”插入失败。只要插入成功,我不介意每次插入等待 10 秒。

最佳答案

文档(由创建此软件并生活、呼吸和思考多年的人编写)告诉您不要共享数据库连接。你为什么不简单地相信他们?创建多个数据库连接并不是真的很难。

  1. 是的,这是真的。可能发生的最糟糕的事情是未定义的行为,这可能包括也可能不包括召唤黑洞、裸奇点和克苏鲁。

  2. 你很幸运。可能在下一个线程开始之前,测试中的所有一百个插入都已经执行。

  3. 您的假设是正确的。您可以通过测试来避免失败,如果遇到失败则重复 SQL 命令。设置高超时不会有帮助。

Sqlite 不是特别适合任何多线程(或多进程)访问数据库的问题,根据我的经验,在这种情况下“数据库已锁定”消息几乎是不可避免的。您可以通过仅从单个线程访问数据库并将插入组合到单个语句中(即使用多值插入)来获得更好的性能。如果这还不够,用多线程锤击 sqlite 数据库将根本不会提高性能。如果您的用例似乎有必要采用这种方法,则应考虑安装为此目的构建的数据库,例如 PostgreSQL。

关于database - SQLite3 的线程安全性如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35717263/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com