SQLite Exception: SQLite Busy - PullRequest
       26

SQLite Exception: SQLite Busy

10 голосов
/ 08 июня 2009

Может ли кто-нибудь предоставить какую-либо информацию об этой ошибке. Я пытаюсь вставить в таблицу, используя Цель C.

При этом я получаю сообщение об ошибке SQLite Busy. Почему это происходит?

Ответы [ 5 ]

21 голосов
/ 08 июня 2009

Если в результате при вызове функции sqlite3 вы получите код ошибки SQLITE_BUSY, это означает, что drdaeman заметил, что БД была заблокирована тем же процессом или одним потоком в вашем процессе.

Правильный способ справиться с этой ситуацией - попробовать выполнить операцию в цикле, и, если код возврата все еще 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 очень удобен и намного проще в использовании для прямого доступа через нативные API C.

8 голосов
/ 14 апреля 2011

У меня была похожая проблема с SQLITE_BUSY для последовательных команд INSERT INTO. Первая строка вставлена ​​нормально, но когда приложение попыталось вставить вторую строку, я получил статус SQLITE_BUSY. После изучения Google я узнал, что вы должны вызывать sqlite3_finalize () для операторов после их выполнения: http://www.sqlite.org/c3ref/finalize.html. Завершение моих утверждений решило мою проблему.

8 голосов
/ 08 июня 2009

Если я правильно понял, «занято» означает, что вы не можете получить блокировку. Похоже, что какой-то другой процесс (или поток и т. Д.) Заблокирован для базы данных.

Блокировка файлов и параллелизм в SQLite версии 3

4 голосов
/ 13 ноября 2013

В моем случае я забыл закрыть базу данных после ее использования. Следующая исправленная шахта:

sqlite3_finalize(statement);
sqlite3_close(contactDB);

FMDB также может легко избавить вас от этих головных болей.

0 голосов
/ 24 января 2019

Я знаю, что уже поздно, но если кто-то ищет более подробное объяснение причин возникновения ошибки, пожалуйста, посмотрите на https://www.activesphere.com/blog/2018/12/24/understanding-sqlite-busy. Я написал это, надеясь, что это поможет людям лучше понять параллелизм в SQLite. .

Он охватывает различные сценарии, при которых может возникнуть ошибка, в разных режимах SQLite (в первую очередь журнал отката и WAL). Также рассматриваются способы правильной обработки таких ошибок (повторные попытки с busy_timeout могут не всегда завершаться успешно, а также повторная попытка отдельных запросов вручную может привести к тупику).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...