MyS*_*DBA 10 sqlite iphone exception objective-c
任何人都可以对此错误提供任何输入.我想使用Objective C插入表中.
当我这样做时,我收到错误SQLite Busy.为什么会这样?
Mas*_*aro 21
如果在调用sqlite3函数时得到错误代码SQLITE_BUSY,这意味着drdaeman观察到db已被同一进程或进程中的一个线程锁定.
处理这种情况的正确方法是在循环中尝试操作,如果返回代码仍然是SQLITE_BUSY,则等待一段时间(您决定超时值),然后在下一次循环迭代中重试该操作.
例如,以下代码片段取自Objective C包装器FMDB(http://code.google.com/p/flycode/source/browse/trunk/fmdb)显示如何为查询准备语句时考虑到某些操作可能会返回SQLITE_BUSY:
int numberOfRetries = 0;
BOOL retry = NO;
if (!pStmt) {
do {
retry = NO;
rc = sqlite3_prepare(db, [sql UTF8String], -1, &pStmt, 0);
if (SQLITE_BUSY == rc) {
retry = YES;
usleep(20);
if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) {
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
NSLog(@"Database busy");
sqlite3_finalize(pStmt);
[self setInUse:NO];
return nil;
}
}
else if (SQLITE_OK != rc) {
if (logsErrors) {
NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
NSLog(@"DB Query: %@", sql);
if (crashOnErrors) {
NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
}
}
sqlite3_finalize(pStmt);
[self setInUse:NO];
return nil;
}
}
while (retry);
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果你需要访问sqlite,FMDB非常方便,并且在通过本机C API直接访问方面使用起来要简单得多.
就我而言,我在使用它后忘记关闭数据库。以下固定矿山:
sqlite3_finalize(statement);
sqlite3_close(contactDB);
Run Code Online (Sandbox Code Playgroud)
FMDB还可以轻松减轻您的这些头痛。
小智 5
我知道这已经晚了,但如果有人正在寻找有关错误发生原因的更详细解释,请查看https://www.activesphere.com/blog/2018/12/24/understanding-sqlite-busy。我写这篇文章是希望它可以帮助人们更好地理解 SQLite 中的并发性。
它涵盖了不同 SQLite 模式(主要是回滚日志和 WAL)下可能发生错误的不同场景。它还研究了正确处理此类错误的方法(重试busy_timeout可能并不总是成功,手动重试单个查询也可能导致死锁)。
| 归档时间: |
|
| 查看次数: |
27603 次 |
| 最近记录: |