• FMDB-FMDatabaseQueue


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

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

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

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

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

    先来了解下FMDatabaseQueue的用法。

    生气先来建个表热热身

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


    没错,就是这么的简单。

    那么再来插入几条数据

    [objc] view plain copy
     
    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.         }  
    6.     }];  


    恩,很帅气有木有。

    开启事务,再插入一次

    [objc] view plain copy
     
    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.           
    12.     }];  



    对比下效率:

    [objc] view plain copy
     
    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.     }];  
    8.     NSDate* two = [NSDate date];  
    9.       
    10.     NSTimeInterval first = [two timeIntervalSinceDate:one];  
    11.     NSLog(@"first = %lf",first);  
    12.       
    13.       
    14.     NSDate* three = [NSDate date];  
    15.     [self.dbQueue inTransaction:^(FMDatabase *db, BOOLBOOL *rollback) {  
    16.         BOOL result = YES;  
    17.         for (int i = 500; i < 1000; i++) {  
    18.             result =  [db executeUpdate:@"insert into testTable (name) values(?)",[NSString stringWithFormat:@"name-%d",i]];  
    19.             if (!result) {  
    20.                 NSLog(@"break");  
    21.                 *rollback = YES;  
    22.                 break;  
    23.             }  
    24.         }  
    25.           
    26.     }];  
    27.       
    28.     NSDate* four = [NSDate date];  
    29.     NSTimeInterval second = [four timeIntervalSinceDate:three];  
    30.     NSLog(@"second = %lf",second);  


    输出打印:

    [objc] view plain copy
     
    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  

    再看看删除:

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


    看看打印:

    [objc] view plain copy
     
    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,可重入。

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



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

    [objc] view plain copy
     
    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.        }];  
    14.    });  

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

  • 相关阅读:
    Angular项目中引入jQuery
    ERROR in Error: ***Module is not an NgModule
    angular-cli项目报Error encountered resolving symbol values statically. Function calls are not supported.错误的处理。
    在angular项目中使用bootstrap的tooltip插件时,报错Property 'tooltip' does no t exist on type 'JQuery<HTMLElement>的解决方法和过程
    微信小程序学习笔记(四)--框架-视图层
    js打印窗口内容并当窗口内容较长时自动分页
    微信小程序学习笔记(三)--框架-逻辑层
    微信小程序学习笔记(二)--框架-全局及页面配置
    微信小程序学习笔记(一)--创建微信小程序
    在ag-grid表格上实现类似Excel中的按下enter键自动跳转到下一行对应的输入框功能,Angular4开发
  • 原文地址:https://www.cnblogs.com/W-Kr/p/5446229.html
Copyright © 2020-2023  润新知