关于SQLite3中的多线程,我有一个问题。在我的情况下,我有几个进程想要写入同一个SQLite3数据库。
在手册中,它说:
多线程。在此模式下,只要没有单个数据库连接被同时用于两个或更多线程,SQLite就可以安全地由多个线程使用。
我编写了一个示例程序,其中几个(假设为10)线程使用同一个数据库连接向同一数据库的同一个表中插入数据。
CREATE TABLE IF NOT EXISTS StatusTable (ID INTEGER PRIMARY KEY, Thread TEXT NOT NULL, Module TEXT NOT NULL, Status INTEGER NOT NULL);
INSERT是什么?
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 次,然后退出。
根据以上说明,尽管我看不到任何问题,但这是不安全的。
- 使用共享的 sqlite3 对象的 10 个线程,每个插入 100 行:没有插入丢失,也没有超时。
- 使用 10 个线程,每个单独的 sqlite3 对象插入 100 行:一些插入不成功(约为 0.5 至 1%),因为数据库被锁定。
- 使用第一种情况下的两个进程:与第二种情况相同,存在一些损失(约为 0.1%)。
我正在使用 PRAGMA journal_mode=WAL;
和 PRAGMA busy_timeout=10000;
。
现在我的问题是:
- 我不应该在线程之间共享连接对象吗?如果这样做会发生什么坏事?
- 为什么第一种情况(共享 db 连接)可行(所有插入都成功,没有超时)?我该怎么做才能 "打破" SQLite?会发生什么情况?
- 我假设每个线程都应该有自己的连接。如何避免插入失败?在我的示例中,只有插入操作,没有读取器。荒谬的高 busy_timeout(10 秒)不像预期的那样起作用,仍然存在 "database is locked" 插入故障。只要插入成功,我不介意每个插入等待 10 秒。
pragma COMPILE_OPTIONS
。它帮助我找到了SQLite的当前配置。 - OO7