1.單線程:禁用所有的mutex鎖,並發使用時會出錯。當SQLite編譯時加了SQLITE_THREADSAFE=0參數,或者在初始化SQLite前調用sqlite3_config(SQLITE_CONFIG_SINGLETHREAD)時啟用。
2.多線程:只要一個數據庫連接不被多個線程同時使用就是安全的。源碼中是啟用bCoreMutex,禁用bFullMutex。實際上就是禁用數據庫連接和prepared statement(准備好的語句)上的鎖,因此不能在多個線程中並發使用同一個數據庫連接或prepared statement。當SQLite編譯時加了SQLITE_THREADSAFE=2參數時默認啟用。若SQLITE_THREADSAFE不為0,可以在初始化SQLite前,調用sqlite3_config(SQLITE_CONFIG_MULTITHREAD)啟用;或者在創建數據庫連接時,設置SQLITE_OPEN_NOMUTEX flag。
3.串行:啟用所有的鎖,包括bCoreMutex和bFullMutex。因為數據庫連接和prepared statement都已加鎖,所以多線程使用這些對象時沒法並發,也就變成串行了。當SQLite編譯時加了SQLITE_THREADSAFE=1參數時默認啟用。若SQLITE_THREADSAFE不為0,可以在初始化SQLite前,調用sqlite3_config(SQLITE_CONFIG_SERIALIZED)啟用;或者在創建數據庫連接時,設置SQLITE_OPEN_FULLMUTEX flag。
在iOS上,默認使用的是第2種方式編譯的,也就是只有一個線程能夠打開數據庫操作,其他線程要操作數據庫必須等數據庫關閉后才能打開操作。多線程時:每個線程獨立打開數據庫,操作數據庫,操作完后關閉數據庫。打開和關閉都比較費時間,而且要手動控制打開關閉鎖,在每個線程操作不頻率時可用該方法。
如果多個線程頻繁操作數據庫,使用以上方法很容易造成系統崩潰,解決方案:開啟第3種串行模式,使用一個類(單例方式)操作數據庫。
-(BOOL)open { sqlite3_shutdown(); NSLog(@"sqlite3 lib version: %s", sqlite3_libversion()); int err=sqlite3_config(SQLITE_CONFIG_SERIALIZED); if (err == SQLITE_OK) { NSLog(@"Can now use sqlite on multiple threads, using the same connection"); } else { NSLog(@"setting sqlite thread safe mode to serialized failed!!! return code: %d", err); } err = sqlite3_open([VersionDBPath UTF8String], &hSqlite3DB); if(err != SQLITE_OK) { NSLog(@"datebase open error: %d", err); return NO; } return YES; }