在我的应用程序中,后台sqlite线程正在运行...在后台线程中它从Web服务获取数据并将数据插入或更新到数据库中。如果用户从前台插入或删除数据,有时我会崩溃它显示“sqlite dblocked”。但它不会返回sqlite busy错误。
我测试了线程安全模式
NSLog(@" sqlite3_threadsafe() = %d", sqlite3_threadsafe());
显示线程安全是2。
我想检查是否有其他数据库正在写数据,如果db正在写数据..我想在上一次写任务完成后写数据。
如何处理这些情况..
答案 0 :(得分:9)
您可以使用锁(例如线程编程指南的Synchronization部分中列举的那些锁),也可以使用专用的串行队列。例如,创建一个队列:
@property (nonatomic, strong) dispatch_queue_t databaseQueue;
实例化:
self.databaseQueue = dispatch_queue_create("com.company.app.database", 0);
无论何时您想与数据库进行交互,都可以
dispatch_sync(self.databaseQueue, ^{
// do your database activity here
});
如果您想简化生活,FMDB库中有一个FMDatabaseQueue
对象可以为您完成大部分工作(并且通常会大大简化您的数据库交互)。
答案 1 :(得分:2)
当多个线程访问同一个连接时,线程安全模式可以防止崩溃,但不能阻止多个连接相互干扰。
您应该使用公共锁来保护所有数据库事务;使用互斥锁或@synchronized directive。
答案 2 :(得分:1)
来自SQLite docs:
使用SQLITE_THREADSAFE编译时参数选择线程模式。如果不存在SQLITE_THREADSAFE编译时参数,则使用序列化模式。这可以通过-DSQLITE_THREADSAFE = 1显式化。使用-DSQLITE_THREADSAFE = 0时,线程模式是单线程。使用-DSQLITE_THREADSAFE = 2时,线程模式是多线程的。
所以看起来你在多线程模式下有SQLite,但没有序列化。在此模式下,您不能使用来自不同线程的相同的数据库连接,但如果您在每个线程中打开不同的连接,那么您将是安全的。