如果在调用 sqlite3 函数时得到错误代码 SQLITE_BUSY,这意味着根据 drdaeman 的观察,数据库已被同一进程或进程中的一个线程锁定。
处理这种情况的正确方法是在循环中尝试该操作,如果返回码仍然是SQLITE_BUSY,则等待一段时间(您决定超时值),然后在下一个循环迭代中重试该操作。
例如,以下代码片段取自 Objective C 包装器 FMDB(http://code.google.com/p/flycode/source/browse/trunk/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);
}
顺便说一句,如果您需要访问 sqlite,FMDB 非常方便,并且相对于通过本机 C API 直接访问而言使用起来更简单。