【问题标题】:Synchronize sqlite database in objective-C在objective-C中同步sqlite数据库
【发布时间】:2012-02-18 20:45:30
【问题描述】:

我有一个视图,我在后台线程中将数据插入来自服务器的 sqlite 数据库。现在,当用户点击并导航到另一个视图时,我必须从该数据库中读取内容,但我无法获取内容,因为数据库已经在最后一个视图的后台线程中打开并且它给出错误“数据库已锁定”。

注意:这两个操作都在不同的表中,即我在不同的表中写入并从其他表中读取。

sqlite 是否支持多线程,如果支持,那么如何从数据库中删除锁?

【问题讨论】:

    标签: iphone objective-c ios xcode sqlite


    【解决方案1】:

    SQLite 支持多线程。您可以在线程之间共享您的连接句柄/对象,它们会很好地同步访问。

    编辑:将sqlite3 对象(sqlite3_open() 作为第二个参数返回的对象)传递给线程,而不是在线程中重新打开数据库。像这样的:

    sqlite3 *MyDatabase; //Initialized somewhere
    NSArray *DataForThread = [NSArray arrayWithObjects:
        request,
        [NSValue valueWithPointer: MyDatabase],
        nil];
    
    [self performSelectorInBackground:@selector(processResponseInBackground:)        withObject:DataForThread];
    

    在线程内部,像这样恢复 SQLite3 对象:

    sqlite3 *MyDatabase = [[ThreadData objectAtIndex:1] pointerValue];
    

    【讨论】:

    • @Seve 如果您提供一些代码会很好。谢谢
    • 你先。如何打开数据库并启动后台线程?
    • 在第一个视图中,当数据来自服务器时,使用 '[self performSelectorInBackground:@selector(processResponseInBackground:) withObject:request];' 在后台插入数据当我从这个视图导航时,它仍然使用数据库并且数据库被锁定用于另一个视图
    • 如何连接数据库?你是在使用 SQLite 的 C API,还是 Core Data,还是什么?总体思路是将连接作为withObject: 参数的一部分传递给线程。但我不知道你的连接对象是什么。
    • 我正在使用 sqlite'c C API 并使用 sqlite3_open commond 打开数据库。我不知道你在说什么连接对象?
    【解决方案2】:

    SQLite 确实支持多线程,但不支持从多个线程同时访问数据库。

    如果您在 Objective-C 中从多个线程访问 SQLite,您应该使用某种锁定机制来协调对数据库句柄的访问。一种选择是@synchronized 关键字。

    至于在不同线程上发生插入的同时从数据库中读取,您需要发挥创造力。

    一种选择是将这两个表放入两个不同的数据库并创建两个不同的连接。

    进一步阅读在多线程环境中使用 SQLite 的本质:

    http://www.sqlite.org/threadsafe.html

    http://www.sqlite.org/faq.html#q6

    【讨论】:

      【解决方案3】:

      Sqlite 在“写得这么快以避免并发问题”的意义上支持多线程。现实情况是,在只读查询的情况下不应该有锁定问题,但如果你也想写......你可能会遇到 SQLITE_BUSY 错误。 您可以通过多种方式避免它:

      • 要么在同一个线程中进行所有查询(但如果你能做到的话……stackoverflow 上没有问题 :-))

      • 或者,如上所述,将数据库表拆分为两个或多个文件(将并发访问较少或只读访问的表组合在一起)并为每个文件创建不同的数据库连接

      • 或者,如上所述,在执行查询的每个方法(或代码块)上使用线程同步方法(以确保在您启动事务时数据库将被锁定,使用“BEGIN IMMEDIATE TRANSACTION” )

      • 或者,使用 c api 提供的 2 个回调“sqlite_busy_handler”和“sqlite_busy_timeout”来处理 sqlite:busy 错误

      • 或者,在收到锁定错误等待 1-2 秒后重试(我认为最好接近上面的一点)

      我更喜欢减少并发拆分数据库,然后如果需要同步线程访问查询代码。这只是你的选择......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-06
        • 2013-03-17
        • 2012-04-15
        • 2012-04-13
        • 2011-09-14
        • 2016-11-12
        • 1970-01-01
        相关资源
        最近更新 更多