我有一个
iOS
应用程序,它使用一个小技巧/黑客在Objective和Javascript之间在UIWebView中进行通信。
SQLite数据库和模式在启动时使用Safari的Javascript DB接口创建。
当应用程序运行时,每秒钟,Obj-C代码从电路板读取数据,并将数据写入同一个SQLite数据库。同样,每隔一秒,Javascript就会从数据库中读取并执行一些javascript来更新UIWebView。因此,DB文件的负载不多。
在尝试将DB写入DB (我使用fmdb执行所有)时,不时会遇到DB锁定错误:
2014-07-23 23:00:10.328 RLog[716:60b] Unknown error calling sqlite3_step (5: database is locked) eu
2014-07-23 23:00:10.328 RLog[716:60b] DB Query: INSERT INTO DEMO2 (time, tc1, tc2, tc3, tc4, hr) VALUES (?, ?, ?, ?, ?, ?)
2014-07-23 23:00:10.329 RLog[716:60b] Unknown error finalizing or resetting statement (5: database is locked)
2014-07-23 23:00:10.329 RLog[716:60b] DB Query: INSERT INTO DEMO2 (time, tc1, tc2, tc3, tc4, hr) VALUES (?, ?, ?, ?, ?, ?)
2014-07-23 23:00:10.329 RLog[716:60b] RLog: err code: 5, database is locked该表非常基本,插入代码与基本代码相同,我只是插入一些浮点值:
NSString *insertSql = @"INSERT INTO DEMO2 (time, tc1, tc2, tc3, tc4, hr) VALUES (%f, %f, %f, %f, %f, %f)";
BOOL inTransaction = [_fmdb beginDeferredTransaction];
if ( ! inTransaction ) {
NSLog(@"RLog: err code: %d, %@", [_fmdb lastErrorCode], [_fmdb lastErrorMessage]);
}
BOOL success = [_fmdb executeUpdateWithFormat:insertSql, time, tc1, tc2, tc3, tc4, hr];
if ( ! success ) {
NSLog(@"RLog: err code: %d, %@", [_fmdb lastErrorCode], [_fmdb lastErrorMessage]);
}
[_fmdb commit];奇怪的是,当我执行一些从一个完全独立的SQLite文件中读取的其他操作时,这种情况似乎是经常发生的,这些操作只从Obj-C代码中访问(而不是用于Obj-C和JS之间的通信桥)。
我不知道为什么或者如何用这么少的读写来锁定DB。
发布于 2014-10-09 09:53:56
如果有可能从单独的线程调用这些定时器或并发运行这些定时器,那么您可能需要做的就是直接使用FMDatabaseQueue而不是db,即:
https://github.com/ccgus/fmdb#using-fmdatabasequeue-and-thread-safety
例如,将其作为_fmdb的对等程序保存:
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
self.fmdbQueue = queue;随后:
[_fmdbQueue inDeferredTransaction:(FMDatabase *db, BOOL *rollback) {
// read data from the db
FMResultSet *rs = [db executeQuery:@"select * from foo"];
while ([rs next]) {
…
}
// write data out
NSString *insertSql = @"INSERT INTO DEMO2 (time, tc1, tc2, tc3, tc4, hr) VALUES "
"(%f, %f, %f, %f, %f, %f)";
BOOL success = [_fmdb executeUpdateWithFormat:insertSql, time, tc1, tc2, tc3, tc4, hr];
if ( ! success ) {
NSLog(@"RLog: err code: %d, %@", [_fmdb lastErrorCode], [_fmdb lastErrorMessage]);
*rollback = YES;
return;
}
}]; // commit will be executed automatically for us if we didn't flip the value of *rollback.这样,所有的读/写都会发生,以消除两次尝试同时运行的可能性。
注意:这假设UIWebView (Javascript)没有打开/锁定它。如果是的话,我不知道你如何保护它,除非你将数据库的创建移出javascript (即目标C中的所有内容)。
https://stackoverflow.com/questions/24926597
复制相似问题