如何处理多线程访问sqlite3没有数据库锁定错误

时间:2013-11-17 10:52:11

标签: ios multithreading sqlite

在我的应用程序中,后台sqlite线程正在运行...在后台线程中它从Web服务获取数据并将数据插入或更新到数据库中。如果用户从前台插入或删除数据,有时我会崩溃它显示“sqlite dblocked”。但它不会返回sqlite busy错误。

我测试了线程安全模式

     NSLog(@" sqlite3_threadsafe() = %d", sqlite3_threadsafe());

显示线程安全是2。

我想检查是否有其他数据库正在写数据,如果db正在写数据..我想在上一次写任务完成后写数据。

如何处理这些情况..

3 个答案:

答案 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,但没有序列化。在此模式下,您不能使用来自不同线程的相同的数据库连接,但如果您在每个线程中打开不同的连接,那么您将是安全的。