SQLite异常:SQLite忙碌

时间:2009-06-08 10:14:47

标签: iphone objective-c exception sqlite

任何人都可以提供有关此错误的任何输入。我正在尝试使用Objective C插入表中。

当我这样做时,我收到错误SQLite Busy。为什么会这样?

5 个答案:

答案 0 :(得分: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);
}

顺便说一句,如果你需要访问sqlite,FMDB非常方便,而且在通过本机C API直接访问方面更加简单。

答案 1 :(得分:8)

如果我说得对,“忙”意味着你无法获得锁定。似乎某个其他进程(或线程等)对数据库有锁定。

File Locking And Concurrency In SQLite Version 3

答案 2 :(得分:8)

我对顺序INSERT INTO命令的SQLITE_BUSY有类似的问题。第一行插入正常,但当应用程序尝试插入第二行时,我获得了SQLITE_BUSY状态。在谷歌到来之后,我了解到你必须在执行它们之后在语句上调用sqlite3_finalize():http://www.sqlite.org/c3ref/finalize.html。完成我的陈述解决了我的问题。

答案 3 :(得分:4)

就我而言,我忘了在使用它之后关闭数据库。以下固定矿井:

sqlite3_finalize(statement);
sqlite3_close(contactDB);

FMDB也可以轻松缓解您的这些麻烦。

答案 4 :(得分:0)

我知道这已经晚了,但是如果有人在寻找有关错误发生原因的更详细说明,请查看https://www.activesphere.com/blog/2018/12/24/understanding-sqlite-busy。我写了这篇文章,希望它可以帮助人们更好地理解SQLite中的并发性。

它涵盖了在不同的SQLite模式(主要是回滚日志和WAL)下可能发生错误的不同情况。它还探讨了正确处理此类错误的方法(使用busy_timeout进行重试可能并不总是成功,而且手动重试单个查询也可能导致死锁)。