Mar*_*ier 6 c++ sqlite multithreading
我正在尝试在多线程 C++ 程序中使用 SQLite 3.7.5。我把它缩小到几行简单的代码:
sqlite3 *Database;
sqlite3_stmt *Stmt;
int retval=sqlite3_open("database.db3",&Database);
retVal=sqlite3_prepare(&Database,"CREATE TABLE RawData (Key CHAR(5))",-1,&Stmt,0);
retval=sqlite3_step(Stmt);
retval=sqlite3_finalize(Stmt);
Run Code Online (Sandbox Code Playgroud)
当我直接从我的主进程调用此代码时,它工作正常。但是,如果我使用 CreateThread() 创建一个线程:
unsigned long ThreadId;
CreateThread(0,0,(LPTHREAD_START_ROUTINE) InserterThread,&Info,0,&ThreadId);
Run Code Online (Sandbox Code Playgroud)
我在sqlite3_step调用中收到“缓冲区溢出”Visual Studio 消息。如果我调试,我会看到崩溃位置在 dbgook.c 的 _CRT_DEBUGGER_HOOK 中。
我正在使用多线程静态 VC 库,并且正在使用定义进行编译:
SQLITE_THREADSAFE=2
THREADSAFE=2
Run Code Online (Sandbox Code Playgroud)
我已经用sqlite3_threadsafe()进行了验证。
我可以稍微追溯一下 SQLite 3 代码,但我希望有人会发现我的代码存在明显的问题并避免我的烦恼。
看来 SQLITE_THREADSAFE 定义是用于编译的,它们不会强制库进入该行为,只是使其可用。
您仍然必须告诉 sqlite 您想要多线程行为,无论是在启动数据库时还是在运行时。
线程模式启动时选择
假设编译时线程模式不是单线程,则可以在初始化期间使用 sqlite3_config() 接口更改线程模式。SQLITE_CONFIG_SINGLETHREAD 动词将 SQLite 置于单线程模式,SQLITE_CONFIG_MULTITHREAD 动词设置多线程模式,SQLITE_CONFIG_SERIALIZED 动词设置序列化模式。
运行时选择线程模式
如果在编译时或启动时未选择单线程模式,则可以将单个数据库连接创建为多线程或序列化。无法将单个数据库连接降级为单线程模式。如果编译时或启动时模式是单线程,也不可能升级单个数据库连接。
单个数据库连接的线程模式由作为 sqlite3_open_v2() 的第三个参数给出的标志确定。SQLITE_OPEN_NOMUTEX 标志使数据库连接处于多线程模式,而 SQLITE_OPEN_FULLMUTEX 标志使连接处于序列化模式。如果两个标志均未指定,或者使用 sqlite3_open() 或 sqlite3_open16() 而不是 sqlite3_open_v2(),则使用由编译时和启动时设置确定的默认模式。
引用自http://www.sqlite.org/threadsafe.html