FMDB封装了SQLite3的方法,操作数据库变得很简单。

增删改查变简单之后,那么问题来了,如何使用多线程优化对数据库的操作?

这是我们的第一反应估计是dispatch_async().

那么问题又来了,多线程操作如何防止database被lock?

哇哈哈,这个时候就要用到FMDatabaseQueue。

先来了解下FMDatabaseQueue的用法。

先来建个表热热身

  1. NSString* path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/test.db"];
  2. NSLog(@"path = %@",path);
  3. self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:path];
  4. [self.dbQueue inDatabase:^(FMDatabase *db) {
  5. BOOL result =  [db executeUpdate:@"create table if not exists testTable (id integer PRIMARY KEY AUTOINCREMENT, name text)"];
  6. NSLog(@"creare %@",result?@"success":@"fail");
  7. }];

没错,就是这么的简单。

那么再来插入几条数据

  1. [self.dbQueue inDatabase:^(FMDatabase *db) {
  2. for (int i = 0; i < 500; i++) {
  3. [db executeUpdate:@"insert into testTable (name) values(?)",[NSString stringWithFormat:@"name-%d",i]];
  4. }
  5. }];

恩,很帅气有木有。

开启事务,再插入一次

  1. [self.dbQueue inTransaction:^(FMDatabase *db, BOOLBOOL *rollback) {
  2. BOOL result = YES;
  3. for (int i = 500; i < 1000; i++) {
  4. result =  [db executeUpdate:@"insert into testTable (name) values(?)",[NSString stringWithFormat:@"name-%d",i]];
  5. if (!result) {
  6. NSLog(@"break");
  7. *rollback = YES;
  8. break;
  9. }
  10. }
  11. }];

对比下效率:

  1. NSDate* one = [NSDate date];
  2. [self.dbQueue inDatabase:^(FMDatabase *db) {
  3. for (int i = 0; i < 500; i++) {
  4. [db executeUpdate:@"insert into testTable (name) values(?)",[NSString stringWithFormat:@"name-%d",i]];
  5. }
  6. }];
  7. NSDate* two = [NSDate date];
  8. NSTimeInterval first = [two timeIntervalSinceDate:one];
  9. NSLog(@"first = %lf",first);
  10. NSDate* three = [NSDate date];
  11. [self.dbQueue inTransaction:^(FMDatabase *db, BOOLBOOL *rollback) {
  12. BOOL result = YES;
  13. for (int i = 500; i < 1000; i++) {
  14. result =  [db executeUpdate:@"insert into testTable (name) values(?)",[NSString stringWithFormat:@"name-%d",i]];
  15. if (!result) {
  16. NSLog(@"break");
  17. *rollback = YES;
  18. break;
  19. }
  20. }
  21. }];
  22. NSDate* four = [NSDate date];
  23. NSTimeInterval second = [four timeIntervalSinceDate:three];
  24. NSLog(@"second = %lf",second);

输出打印:

  1. 2014-11-18 22:01:57.756 FMDB[7489:230565] path = /Users/zhutc/Library/Developer/CoreSimulator/Devices/9001525C-7201-480E-ADC8-8F77C160A18F/data/Containers/Data/Application/6D0C0AE6-3069-4BEE-A7B9-1161C73540BD/Documents/test.db
  2. 2014-11-18 22:01:57.759 FMDB[7489:230565] creare success
  3. 2014-11-18 22:02:03.029 FMDB[7489:230565] first = 5.270233
  4. 2014-11-18 22:02:03.052 FMDB[7489:230565] second = 0.022609

再看看删除:

  1. NSDate* five = [NSDate date];
  2. [self.dbQueue inDatabase:^(FMDatabase *db) {
  3. [db executeUpdate:@"delete from testTable where id < 500"];
  4. }];
  5. NSDate* six = [NSDate date];
  6. NSTimeInterval third = [six timeIntervalSinceDate:five];
  7. NSLog(@"third = %lf",third);
  8. NSDate* seven = [NSDate date];
  9. [self.dbQueue inTransaction:^(FMDatabase *db, BOOLBOOL *rollback) {
  10. [db executeUpdate:@"delete from testTable where  id >= 500"];
  11. }];
  12. NSDate* eight = [NSDate date];
  13. NSTimeInterval fourth = [eight timeIntervalSinceDate:seven];
  14. NSLog(@"fourth = %lf",fourth);

看看打印:

  1. 2014-11-18 22:02:03.066 FMDB[7489:230565] third = 0.013382
  2. 2014-11-18 22:02:03.080 FMDB[7489:230565] fourth = 0.013715

还是事务高大上!!!

可以看出来:使用事务处理就是将所有任务执行完成以后将结果一次性提交到数据库,如果此过程出现异常则会执行回滚操作,这样节省了大量的重复提交环节所浪费的时间。

多线程在哪里?

看下FMDatabaseQueue的源码,发现了一个串行的queue,而且这个queue是同步调用

这个源码是比较老得,最新版的没下载下来,就拿过来用用。最新版的变动是使用同一个queue,可重入。

  1. - (void)inDatabase:(void (^)(FMDatabase *db))block {
  2. FMDBRetain(self);
  3. dispatch_sync(_queue, ^() {
  4. FMDatabase *db = [self database];
  5. block(db);
  6. if ([db hasOpenResultSets]) {
  7. NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
  8. }
  9. });
  10. FMDBRelease(self);
  11. }

到这里应该就知道,我们只需要使用dispatch_async,然后配合FMDatabaseQueue。

  1. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  2. [self.dbQueue inTransaction:^(FMDatabase *db, BOOLBOOL *rollback) {
  3. BOOL result = YES;
  4. for (int i = 500; i < 1000; i++) {
  5. result =  [db executeUpdate:@"insert into testTable (name) values(?)",[NSString stringWithFormat:@"name-%d",i]];
  6. if (!result) {
  7. NSLog(@"break");
  8. *rollback = YES;
  9. break;
  10. }
  11. }
  12. }];
  13. });

最新版的FMDB不可以在多个队列中使用同一个FMDatabaseQueue实例,会有问题。至于为毛,等研究透了在补充。哇哈哈!1

FMDB-FMDatabaseQueue的更多相关文章

  1. FMDB多线程读写问题,使用FMDataBaseQueue操作可以解决同时打开一个链接de读写问题

    现在ios里使用的数据库一般都是Sqlite,但是使用Sqlite有个不太好的地方就是在多线程的时候,会出现问题,sqlite只能打开一个读或者写连结.这样的话多线程就会碰到资源占用的问题. 最开始是 ...

  2. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  3. FMDB的使用方法

    转自:http://blog.devtang.com/blog/2012/04/22/use-fmdb/ 前言 SQLite (http://www.sqlite.org/docs.html) 是一个 ...

  4. FMDB 排它锁

    -------------------------------------基本操作------------------------------------- #import "ViewCon ...

  5. IOS数据存储之FMDB数据库

    前言: 最近几天一直在折腾数据库存储,之前文章(http://www.cnblogs.com/whoislcj/p/5485959.html)介绍了Sqlite 数据库,SQLite是一种小型的轻量级 ...

  6. FMDB第三方框架

    FMDB是同AFN,SDWebImage同样好用的第三方框架,它以OC的方式封装了SQLite的C语言API,使得开发变得简单方便. 附上github链接https://github.com/ccgu ...

  7. FMDB 数据库

    iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便.于是,就出现了一系列将SQLite API进行封装的库,例如FMDB.PlausibleDatabase.sqlitepers ...

  8. 【原】iOS学习47之第三方-FMDB

    将 CocoaPods 安装后,按照 CocoaPods 的使用说明就可以将 FMDB 第三方集成到工程中,具体请看博客iOS学习46之第三方CocoaPods的安装和使用(通用方法) 1. FMDB ...

  9. FMDB

    一.FMDB简介 1.FMDB简介 iOS中原生的SQLite API在进行数据存储的时候,需要使用C语言中的函数,操作比较繁琐.于是,就出现了一系列将SQLite API进行封装的库,例如FMDB. ...

  10. FMDB浅析

    一.FMDB介绍 FMDB是一种第三方的开源库,FMDB就是对SQLite的API进行了封装,加上了面向对象的思想,让我们不必使用繁琐的C语言API函数,比起直接操作SQLite更加方便. FMDB优 ...

随机推荐

  1. 【Spark机器学习速成宝典】模型篇08保序回归【Isotonic Regression】(Python版)

    目录 保序回归原理 保序回归代码(Spark Python) 保序回归原理 待续... 返回目录 保序回归代码(Spark Python) 代码里数据:https://pan.baidu.com/s/ ...

  2. 如何用ORM自定义排序

    ORM连接的数据库不同,方法也不同 postgresql: a.extra(select={"new_order":"position(status in '2,3,4, ...

  3. [MVC HtmlHelper简单了解]

    HtmlHelper用来在视图中显示Html控件,简化代码,使用方便!,降低了View视图中的代码复杂度!可以更快速的完成工作! 以下是一些常用 的html标签 辅助方法 使用HTML辅助方法输出   ...

  4. hibernate本地验证

    下载hibernate验证文件,将其拷贝到工程根目录 下,验证中这样写 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/H ...

  5. JavaScript日常学习4

    JavaScript事件 1.<button id="btn1" onclick="document.getElementById("btn1" ...

  6. 安装SQL Server 2008反复提示需要安装MICROSOFT NET FRAMEWORK 3 5 SP1的一个

    在安装过.net  framework 4的系统中,安装sql server 2008的安装前提之一MICROSOFT .NET FRAMEWORK 3.5 SP1时,可能已经安装并重启了,还是提示安 ...

  7. cento7忘记root密码怎么办

    1.首先开启系统,一直按 e 键 进入编辑选项 2.光标下移,在UTF-8行这一段修改两处,首相找到ro改为rw,即只读改为可读写权限:然后在这段的尾部加入 init=/bin/sh 3.此时按住Ct ...

  8. git clone 指定分支操作

    服务器迁移,而且原来本地开发是在同一个目录中切换不同的分支,感觉有点挫,于是打算一个文件目录对应一个分支,这样不会有太大的文件差异. 记录下来本次操作,可能以后还会用到. git初始化一般是这样. g ...

  9. AWSome Day简介

    AWSome Day是什么? 它是一场为时一天.结合教育与技术新知的云计算技术免费研讨会.是面向所有开发人员.IT技术人员.或技术/业务领域决策者必备的基础云计算课程.AWS专业级讲师将在现场带领您从 ...

  10. 【神经网络与深度学习】【VS开发】【CUDA开发】VS2013 配置CUDNN V4 DEMO

    VS2013 配置CUDNN V4 DEMO 众所周知,当前主流深度学习的实现中调用的底层API都是cudnn,自己做项目需要开发深度学习模块时,也需要调用cudnn库,因此熟悉cudnn库是很有必要 ...