ios – 在多个线程和两个连接上使用FMDB

ios – 在多个线程和两个连接上使用FMDB,第1张

概述我在我的应用程序中使用两种不同类型的fmdb连接: FMDatabase用于所有READ查询和 所有UPDATE查询的FMDatabaseQueue. 两者都由单例处理,它在应用程序运行时保持两种类型的打开. 读取和更新查询都在不同的线程中使用,因为我的应用程序中的某些任务在后台进行;例如从服务器获取数据,并通过FMDatabaseQueue将其插入到自己的后台线程中,同时通过FMDatabase 我在我的应用程序中使用两种不同类型的fmdb连接:

FMDatabase用于所有READ查询和
所有UPDATE查询的FMDatabaseQueue.

两者都由单例处理,它在应用程序运行时保持两种类型的打开.

读取和更新查询都在不同的线程中使用,因为我的应用程序中的某些任务在后台进行;例如从服务器获取数据,并通过FMDatabaseQueue将其插入到自己的后台线程中,同时通过FMDatabase从db读取一些信息,并在主线程上更新VIEwController.

我的问题是,通过FMDatabaseQueue将数据插入数据库后,第二个连接(FMDatabase)不会返回更新的信息,因为它们没有找到它们.但是我知道数据被插入,因为我已经用db浏览器工具检查了db,而插入它没有错误.为了避免这种情况,我必须关闭FMDatabase数据库连接并重新打开它以查看其他连接所做的更改.不幸的是,当我的应用程序启动时,有许多插入,更新读取,因为大量的新数据从需要处理的服务器加载 – 因此,每当更新发生时,在许多“数据库繁忙”消息中关闭和打开数据库.

我已经为所有线程使用了一个单一的FMDatabaseQueue,然后执行(读取和更新),但是当使用带有__block变量的读取查询将结果集从回调中取出时相当慢,而另一个线程执行一些插入(在50-100之间)单笔交易).

在它的顶部,数据库通过sqlcipher加密 – 不知道如果它是重要的,但想提到它.所以每次我必须关闭并打开数据库,我正在做一个setKey.

我的问题:是否可以在多个线程上使用具有两种不同连接类型的设置,如果是,是否必须关闭并打开FMDatabase连接?还是有更好的解决方案?

UPDATE

我的代码执行插入/更新看起来像

-(voID) create:(NSArray *)transactions{    NSMutableString *sqlquery = [[NSMutableString alloc] initWithString:STANDARD_INSERT_query];    [sqlquery appendString:@"(transaction_ID,name,date) VALUES (?,?,?)"];    FMDBDataSource *ds = [FMDBDataSource sharedManager];    FMDatabaseQueue *queue = [ds getFMDBQ];    [queue inTransaction:^(FMDatabase *db,BOol *rollback) {        [db setKey:[ds getKey]]; // returns the key to decrypt the database        for (Transaction *transaction in transactions)        {            [db executeUpdate:sqlquery,transaction.transactionID,transaction.name,transaction.date];        }    }];}

和一个读取查询

-(Transaction *)read:(Nsstring *)transactionID{    Nsstring *sqlquery = [[Nsstring alloc] initWithString:STANDARD_SELECT_query];    Transaction *transaction = nil;    FMDBDataSource *ds = [FMDBDataSource sharedManager];    FMResultSet *rs = [[ds getFMDB] executequery:sqlquery];    while ([rs next]) {        transaction = [[Transaction alloc] init];        [transaction setTransactionID:[rs stringForColumn:@"transaction_ID"]];        [transaction setname:[rs stringForColumn:@"name"]];    }[rs close];return transaction;}

FMDBDataSource是一个持有FMDatabase和FMDatabaseQueue连接的单例

- (FMDatabaseQueue *)getFMDBQ{    if (self.fmdbq == nil)    {        self.fmdbq = [FMDatabaseQueue databaseQueueWithPath:[self getDBPath]];    }    return self.fmdbq;}- (FMDatabase *) getFMDB{    if(self.fmdb == nil)    {        self.fmdb = [FMDatabase databaseWithPath:[self getDBPath]];        [self openAndKeyDatabase]; // opens the db and sets the key as the db is encrypted    }    return self.fmdb;}

正如我所说,使用此代码时,FMDatabase连接不会获取通过FMDatabaseQueue插入的信息.

解决方法 就个人而言,我建议为两个线程使用单个 FMDatabaseQueue,并让队列协调两个线程上的动作.这就是为它创造的.它完全消除了这些“数据库忙”问题.

在性能更新中,如果进行批量更新,则在更新之前是否使用FMDatabase方法beginTransaction,最后使用commit?或使用inTransaction方法.在我的测试中插入10,000条记录没有交易需要36.8秒,但是事务需要0.25秒.

或者,如果您的批量更新是必要的缓慢(例如,您使用某种流式协议从Web服务下载某些大数据源),您可以:

>首先将所有结果加载到内存中,没有数据库交互,然后使用上一段所述的交易的批量更新;要么
>如果您的数据库更新必然受到较慢的网络连接的约束,则使用单独的inDatabase调用,以便在从Web服务下载数据时不会调出FMDatabaseQueue.

底线,通过使用事务或明智地使用单独的inDatabase调用,可以最大限度地减少后台 *** 作涉及FMDatabaseQueue的时间,并且可以实现与数据库的同步多线程交互,而不会太大地阻止用户界面.

总结

以上是内存溢出为你收集整理的ios – 在多个线程和两个连接上使用FMDB全部内容,希望文章能够帮你解决ios – 在多个线程和两个连接上使用FMDB所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1110168.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存