Jon*_*nas 4 sqlite objective-c fmdb ios
我相信我的用例相当普遍,但我找不到对此的权威答案。
我有一个在后台运行并将数据写入我的数据库的同步机制。这种同步可能需要很长时间(我使用 FTS)。为此,我使用FMDatabaseQueue. 当我想读取数据库时,我使用相同的队列进行查询。
现在,当同步进程已经将大量事务排队到队列中时,应用程序想要进行读取,它必须等待所有写入事务完成才能进行查询,因为这是一个串行队列。代码可能如下所示:
FMDatabaseQueue *queue = [self getDatabaseQueue];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
// Very slow process
[db executeUpdate:@"UPDATE docs SET name = ?", "value..."];
}];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
// Very slow process
[db executeUpdate:@"UPDATE docs SET name = ?", "value..."];
}];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
// Very slow process
[db executeUpdate:@"UPDATE docs SET name = ?", "value..."];
}];
[queue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet = [db executeQuery:@"SELECT name..."];
}];
Run Code Online (Sandbox Code Playgroud)
我想立即获得查询结果(即使同步未完成),而不是等待UPDATE完成。
我可以创建两个FMDatabaseQueues,一个用于写查询,一个用于读查询?如果读查询在写事务的中间开始会发生什么?
代码可能如下所示:
FMDatabaseQueue *writeQueue = [self getWriteDatabaseQueue];
FMDatabaseQueue *readQueue = [self getReadDatabaseQueue];
[writeQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
// Very slow process
[db executeUpdate:@"UPDATE docs SET name = ?", "value..."];
}];
[writeQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
// Very slow process
[db executeUpdate:@"UPDATE docs SET name = ?", "value..."];
}];
[writeQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
// Very slow process
[db executeUpdate:@"UPDATE docs SET name = ?", "value..."];
}];
[readQueue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet = [db executeQuery:@"SELECT name..."];
}];
Run Code Online (Sandbox Code Playgroud)
编辑:
此外,让我感到困惑的是文档说明:
每个线程都可以创建一个 FMDatabase 对象。只是不要跨线程共享单个实例。
所以我从中了解到的是,我可以使用相同的数据库创建两个实例,但我只需要将它保留在自己的线程上。
不,您不想让两个FMDatabaseQueue与同一个数据库交互。整个目的FMDatabaseQueue是提供一个队列,用于通过共享的单个串行队列协调来自不同线程的数据库调用。
不过,我想知道您在“非常慢的进程”块中的代码。如果这不是特定于数据库的东西,那么它不应该在inTransaction和/或inDatabase调用中。
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
FMDatabaseQueue *databaseQueue = [FMDatabaseQueue databaseWithPath:path];
[backgroundQueue addOperationWithBlock:^{
// very slow process
[databaseQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:@"UPDATE docs SET name = ?", "value..."];
}];
}];
[backgroundQueue addOperationWithBlock:^{
// very slow process
[databaseQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:@"UPDATE docs SET name = ?", "value..."];
}];
}];
Run Code Online (Sandbox Code Playgroud)
当那些排队并运行时,主队列可以进行自己的databaseQueue调用,使用FMDatabaseQueue来确保以这种方式进行协调,使其不会与上述inTransaction块同时发生:
[databaseQueue inDatabase:^(FMDatabase *db) {
FMResultSet *resultSet = [db executeQuery:@"SELECT name..."];
while (![resultSet next]) {
....
}
}];
Run Code Online (Sandbox Code Playgroud)
显然,你应该管理你的后台任务,但它适合你的应用程序(我使用了并发操作队列,但你可以使用串行队列或调度队列或任何你想要的)。不要被backgroundQueue上面的细节所困扰,因为您的实现会有所不同。
关键的观察是您不应该使用databaseQueue来管理您的“非常慢的进程”任务以及数据库交互。从inTransactionandinDatabase调用中取出与数据库无关的任何内容。使用您自己的队列来管理您自己的非数据库相关代码。始终databaseQueue尽可能快地进出,并让单个共享FMDatabaseQueue协调与来自多个线程的数据库的交互。
| 归档时间: |
|
| 查看次数: |
2701 次 |
| 最近记录: |