objective-c SQLite 异常:SQLite 忙

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/964207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:41:09  来源:igfitidea点击:

SQLite Exception: SQLite Busy

iphoneobjective-cexceptionsqlite

提问by MySQL DBA

Can anyone provide any input on this error. I am trying to insert into table using Objective C.

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

While I am doing this, I am getting an error SQLite Busy. Why this is happening?

当我这样做时,我收到错误 SQLite Busy。为什么会发生这种情况?

采纳答案by drdaeman

If I get it right, "busy" means that you cannot obtain a lock. Seems that some another process (or thread, etc) has a lock on a database.

如果我说得对,“忙”意味着您无法获得锁。似乎另一个进程(或线程等)锁定了数据库。

File Locking And Concurrency In SQLite Version 3

SQLite 版本 3 中的文件锁定和并发

回答by Massimo Cafaro

If you get as a result when invoking an sqlite3 function the error code SQLITE_BUSY, this means as observed by drdaeman that the db has been locked by the same process or by one thread within your process.

如果在调用 sqlite3 函数时得到错误代码 SQLITE_BUSY,这意味着 drdaeman 观察到该数据库已被同一进程或进程中的一个线程锁定。

The proper way to deal with this situation is to try the operation in a loop, and if the return code is still SQLITE_BUSY, to wait for some time (you decide the timeout value) and then retry the operation in the next loop iteration.

处理这种情况的正确方法是在循环中尝试操作,如果返回码仍然是SQLITE_BUSY,则等待一段时间(您决定超时值),然后在下一次循环迭代中重试操作。

For instance, the following code snippet is taken from the Objective C wrapper FMDB (http://code.google.com/p/flycode/source/browse/trunk/fmdb) shows how to prepare a statement for a query taking into account that some operations may return 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);
}

By the way, if you need to access sqlite, FMDB is very handy and much simpler to use with respect to direct access through the native C APIs.

顺便说一下,如果您需要访问 sqlite,FMDB 非常方便,而且相对于通过本机 C API 直接访问而言使用起来要简单得多。

回答by stephenhow

I had a similar problem with SQLITE_BUSY on sequential INSERT INTO commands. The first row inserted ok, but when the app tried to insert a second row, I got the SQLITE_BUSY status. After Google'ing around, I learned you must call sqlite3_finalize() on statements after executing them: http://www.sqlite.org/c3ref/finalize.html. Finalizing my statements fixed my problem.

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

回答by Saqib Saud

In my case, I had forgotten to close database after using it. Following fixed mine:

就我而言,我在使用后忘记关闭数据库。以下固定矿山:

sqlite3_finalize(statement);
sqlite3_close(contactDB);

FMDBcan also alleviate these headaches from you easily.

FMDB还可以轻松减轻您的这些头痛。

回答by Rahul Jayaraman

I know this is late, but if anyone is looking for a more detailed explanation on why the error occurs, please have a look at https://www.activesphere.com/blog/2018/12/24/understanding-sqlite-busy. I wrote this, hoping it might help people understand concurrency in SQLite better.

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

It covers different scenarios under which the error might occur, in different SQLite modes (Rollback journal and WAL primarily). It also looks at ways to correctly handle such errors (retries with busy_timeoutmight not always succeed, also manually re-trying individual queries might lead to a deadlock).

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