我有一个使用 SQLite(版本 3.7.2)来存储数据的应用程序。我有一个在多个线程之间共享的 SQLite 连接,这些线程从同一个 SQLite 数据库写入和读取。 SQLite 是用 DSQLITE_THREADSAFE=1 编译的,这意味着 SQLite 处于序列化模式。
引用自SQLite文档
序列化:在序列化模式下,SQLite可以被多个安全地使用 没有限制的线程。
相反,SQLite Wiki条目说
不要在多个时间同时使用同一个数据库连接 一根线
我尝试使用一个示例应用程序,该应用程序生成数百个线程并共享 SQLite 句柄来读取和写入,工作正常。
那么 SQLite wiki 条目是否已过时,或者 SQLite 可能无法使用同一连接同时处理不同线程发生的读写?
编辑
DSQLITE_THREADSAFE=2:多线程模式 SQLite 中的术语“多线程”有点令人困惑。似乎在多线程模式下,您无法与其他线程共享连接,因为连接本身不会使用互斥体来防止一个线程在另一个线程正在使用它时修改连接。
DSQLITE_THREADSAFE=1:序列化模式 但是,在serialized模式下,它将锁定数据文件并使用互斥体来控制共享连接的访问。
来自文档: ...当使用 SQLITE_THREADSAFE=1 编译 SQLite 时,SQLite 库本身将序列化对数据库连接和预准备语句的访问,以便应用程序可以同时在不同线程中自由使用相同的数据库连接或相同的预准备语句。
因此,在处理连接时,序列化模式是线程安全,但多线程模式不是,尽管您仍然可以对同一数据库有多个连接。
来源:http://www.sqlite.org/c3ref/c_config_getmalloc.html#sqliteconfigmultithread
当 DSQLITE_THREADSAFE=0 时,在多个线程之间共享一个连接是一个坏主意
想象您的线程 1 正在执行此代码:
1. connection.setAutoCommit(false);
2. statement.executeUpdate(sql);
3. connection.commit();
并且您的线程 2 正在同时执行此代码:
1. connection.setAutoCommit(true);
现在,如果 THREAD 2 的指令 1 正好在 THREAD 1 的指令 3 之前执行怎么办?您可能会收到一个 SQLException,其中包含消息“数据库处于自动提交模式”(因为自动提交方法是在同一个 Connection 对象上执行的)。
这意味着应该使用 DSQLITE_THREADSAFE=1 来同步他的代码
如果您要开发多线程代码,那么使用连接池也是最好的选择,当您决定选择另一个 DBMS 时,您可以获得更好的性能。