zoukankan      html  css  js  c++  java
  • IOS 使用FMDB多线程访问数据库 及databaseislocked的问题

    原理:文件数据库sqlite,同一时刻允许多个进程/线程读,但同一时刻只允许一个线程写。在操行写操作时,数据库文件被琐定,此时任何其他读/写操作都被阻塞,如果阻塞超过5秒钟(默认是5秒,能过重新编译sqlite可以修改超时时间),就报"database is locked"错误。

    所以,在操作sqlite时,应该即时关闭连接;打开连接后,尽量减少非常费时的操作。

    多线程同时访问数据库时,报数据库锁定的问题,错误信息是:

    Unknown error finalizing or resetting statement (5: database is locked)

    最后通过FMDatabaseQueue解决了这个问题,本文总结一下:

    FMDatabase 不能多线程使用一个实例

    多线程访问数据库,不能使用同一个FMDatabase 的实例。否则会发生异常。如果线程使用单独的FMDatabase 实例是允许的,但是同样有可能发生database is locked的问题。这是由于多线程对sqlite的竞争引起的

    FMDatabaseQueue 解决这个问题的思路是:创建一个队列,然后将放入的队列的block顺序执行,这样避免了多线程同时访问数据库

    解决方案 共享同一个FMDatabaseQueue实例

    创建一个DBHelper 类

    使用FMDatabaseQueue之后,管理db

    原本使用FMDatabase类,需要手工调用db的open和close方法

    但是用FMDatabaseQueue,不需要调用open,因为查看代码发现,Queue已经open了。至于要不要close,我也不确定,因为官方的sample code没有调用close。实际应用中,我也没有调用,好像没有问题。

    所以,使用Queue,是不需要自己打开和关闭db的。但是如果使用了FMResultSet,rs倒是需要关闭,否则会报warning:

    if ([db hasOpenResultSets]) {

    NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");

    为了不看到warning,我都在block里调用了[rs close]

    刷新数据库文件路径

    具体到我们的应用,还有一个特殊问题需要考虑。因为我们的APP可以切换账户,而账户的db文件是独立的。所以当用户重新登录的时候,需要刷新一下Helper的queue

    如果不这么做,由于Helper是单例,那么切换账户以后,用户B访问的还是用户A的数据库。刷新的调用,一般放在登录之后,进入主页面之前就可以了

  • 相关阅读:
    并查集
    贪心
    分治
    二分
    操作系统基础知识--《操作系统原理(第4版)(普通高等教育"十一五"国家级规划教材)》读书笔记
    《自控力》读书记录
    计算机组成原理基础知识--《计算机组成原理与汇编语言程序设计(第4版)(高等学校规划教材)》读书笔记
    ansible自动部署模板文件中列表长度判断
    《股市稳赚》摘录
    yarn学习小结
  • 原文地址:https://www.cnblogs.com/camillezlh/p/4739378.html
Copyright © 2011-2022 走看看