我有一个使用的iOS应用程序,sqlite3我正面临多线程问题,使应用程序崩溃illegal multi-threaded access to database connection.当然,这是因为我正在使用多线程; 问题是,我的sqlyte3实例配置为使用多线程:
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
Run Code Online (Sandbox Code Playgroud)
即使我使用多线程(sqlite3构建也使用多线程标志编译),当多个线程同时写入或读取数据库时,它会导致我的应用程序崩溃.
崩溃报告
Application Specific Information:
BUG IN CLIENT OF sqlite3.dylib: illegal multi-threaded access to database connection
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001823ed2fc
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [0]
Triggered by Thread: 12
Thread 12 Crashed:
0 libsqlite3.dylib 0x00000001823ed2fc sqlite3MutexMisuseAssert + 144 (sqlite3.c:23788)
1 libsqlite3.dylib 0x00000001823ed2ec sqlite3MutexMisuseAssert + 128 (once.h:84)
2 libsqlite3.dylib 0x000000018235248c sqlite3LockAndPrepare + 320 (sqlite3.c:23801)
3 MyCodeCall.m ...........
Run Code Online (Sandbox Code Playgroud)
我已经在这个问题上苦苦挣扎了一段时间,我在谷歌上找不到任何关于这个问题的不幸.
UPDATE
+(sqlite3*) getInstance {
if (instance == NULL) {
sqlite3_shutdown();
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
sqlite3_initialize();
NSLog(@"isThreadSafe %d", sqlite3_threadsafe());
const char *path = [@"./path/to/db/db.sqlite" cStringUsingEncoding:NSUTF8StringEncoding];
if (sqlite3_open_v2(path, &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) {
NSLog(@"Database opening failed!");
}
}
return instance;
}
Run Code Online (Sandbox Code Playgroud)
len*_*ndc 15
事实证明,SQLITE_CONFIG_MULTITHREAD只要您不同时使用相同的连接,模式在多线程环境中运行良好; 这恰好是我的确切场景.因此,要解决此问题,您可以为每个线程打开一个新连接,也可以SQLITE_CONFIG_SERIALIZED使用SQLITE_OPEN_FULLMUTEX标志在完全互斥模式下打开连接.
辅助方法最终如下:
+(sqlite3*) getInstance {
if (instance == NULL) {
sqlite3_shutdown();
sqlite3_config(SQLITE_CONFIG_SERIALIZED);
sqlite3_initialize();
NSLog(@"isThreadSafe %d", sqlite3_threadsafe());
const char *path = [@"./path/to/db/db.sqlite" cStringUsingEncoding:NSUTF8StringEncoding];
if (sqlite3_open_v2(path, &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX, NULL) != SQLITE_OK) {
NSLog(@"Database opening failed!");
}
}
return instance;
}
Run Code Online (Sandbox Code Playgroud)
如果有人在 Swift 中遇到这个问题。解决方案将是:
let dbName = "first.db"
static let shared = DatabaseManger()
var db: OpaquePointer?
private init(){
print("singletone initialized")
sqlite3_shutdown();
let dbPath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent(dbName)
if sqlite3_open_v2(dbPath.path, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX, nil) == SQLITE_OK {
print("Successfully opened database connection at \(dbPath.path)")
}
else {
print("unable to open database connection")
}
}
Run Code Online (Sandbox Code Playgroud)
此代码在 swift 版本 4.0 和 4.2 中测试
小智 5
请使用 SQLite 共享缓存模式 https://www.sqlite.org/sharedcache.html
sqlite3_open_v2(path.path, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE, nil) != SQLITE_OK
SQLITE_OPEN_SHAREDCACHE
100%可靠:)
| 归档时间: |
|
| 查看次数: |
4538 次 |
| 最近记录: |