База данных ошибок sqlite заблокирована

У меня есть база данных sqlite в приложении iPhone, которое я пишу. Я получаю сообщение об ошибке со следующим кодом, который я запускаю в фоновом потоке. В фоновом потоке я вызываю этот метод:

 - (BOOL) songIsInDatabase:(NSString *)songTitle
{
NSString *docsDir;
NSArray *dirPaths;

dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];


//Build the path to the database file
NSString *databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent:@"Database.db"]];

const char *dbpath = [databasePath UTF8String];

sqlite3_stmt *statement;

if(sqlite3_open(dbpath, &DB) == SQLITE_OK){

    NSString *insertSQL = [NSString stringWithFormat:@"select * from Bpm_Table where song_title = '%@'", songTitle];

    const char *insert_stmt = [insertSQL UTF8String];
    if(sqlite3_prepare_v2(DB, insert_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        while (sqlite3_step(statement) == SQLITE_ROW)
        {
            return YES;
            break;
        }
    }else{
        NSLog(@"the error is %s", sqlite3_errmsg(DB));
    }
    sqlite3_finalize(statement); 
}

[databasePath release];
return NO;
}

Затем я вызываю этот метод:

- (void) addSongToDatabase: (NSString *) songTitle andBPM: (int)bpm andGenre: (NSString *) genre
{
NSString *docsDir;
NSArray *dirPaths;

dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];


//Build the path to the database file
NSString *databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent:@"Database.db"]];

const char *dbpath = [databasePath UTF8String];

sqlite3_stmt *statement;

if(sqlite3_open(dbpath, &DB) == SQLITE_OK){

    NSString *insertSQL = [NSString stringWithFormat:@"insert or replace into Bpm_Table (song_title, bpm, genre) values (\"%@\", \"%d\", \"%@\")", songTitle, bpm, genre];

    const char *insert_stmt = [insertSQL UTF8String];
    if(sqlite3_prepare(DB, insert_stmt, -1, &statement, NULL) == SQLITE_OK){
        if(sqlite3_step(statement) == SQLITE_DONE)
        {

        } else {
            NSLog(@"error: %s", sqlite3_errmsg(DB));
        }
    }sqlite3_finalize(statement);
}

[databasePath release];
}

Если я запускаю оба этих метода, один за другим, я получаю сообщение об ошибке, в котором говорится, что заблокирована база данных. Я добавил операторы sqlite3_finalize после того, как выкрикнул Google в надежде, что это исправит проблему. Если я прокомментирую какой-либо из методов, я не получу эту ошибку.

Кто-нибудь знает, что неправильно?

Ответ 1

вы должны всегда закрывать базу данных sqlite после ее использования... поэтому добавьте эту строку sqlite3_close(DB); сразу после sqlite3_finalize(statement);

Обновление -

Вы возвращаете ДА в одном из циклов while -

        while (sqlite3_step(statement) == SQLITE_ROW)
        {
            return YES;
            break;
        }

поэтому здесь вы не завершаете и не закрываете базу данных.. вам нужно закрыть, если каждый раз, когда вы его открываете

Ответ 2

ваша база данных открыта, закройте ее, используя sqlite3_close (db) если вы не закрываете, то процесс, который обратился к вашей базе данных, будет работать с фоном что приведет к ошибке блокировки базы данных.

если вы хотите удалить базу данных, это ошибка блокировки, а затем выполните следующие действия. 1. скопируйте файл своей базы данных в другое место. 2. позже замените базу данных скопированной базой данных 3.this будет разыменовывать все процессы, которые обращаются к вашему файлу базы данных

Ответ 3

Но обратите внимание, что если вы получаете доступ к одной и той же SQLite-базе данных из нескольких потоков, без какой-либо отдельной синхронизации (каким-то образом, чтобы знать, что у вас никогда не будет одновременного доступа из нескольких потоков), вы, вероятно, базы данных ", даже если вы закрываете все правильно при каждом доступе.

SQLite не предоставляет никакого механизма блокировки ожидания.

Ваши основные параметры:

  • Делает все обращения из одного потока.
  • Используйте отдельный протокол блокировки во всех доступах.
  • Если вы получаете ошибку с "блокировкой базы данных", подождите короткий период времени и повторите попытку.

Ответ 4

Ваша база данных открыта. Закройте его, используя sqlite3_close(db).

Если вы не закрываете, тогда процесс доступа к вашей базе данных будет запускаться в фоновом режиме, что приведет к блокировке базы данных.

Ответ 5

Если вы пытались использовать sqlite3_close(DB) вероятно, потому что ваши методы пытаются получить доступ к одной и той же базе данных в одно и то же время. Попробуйте разместить эту строку кода

sqlite3_busy_timeout(DB, 500);

где-то между sqlite3_open и sqlite3_prepare_v2 в методе, откуда вы получаете сообщение "база данных заблокирована" -error.

Соединение с базой данных в этом методе затем попытается записать/прочитать за 500 миллисекунд, прежде чем оно сдается, что обычно достаточно для снятия блокировки.

Ответ 6

С одной стороны, вы не закрываете соединение с базой данных с sqlite3_close(), прежде чем открывать новое соединение

Ответ 7

Я просто провел час с той же проблемой. Проблема для меня возникла, когда я невольно убил процесс, закрыв оболочку (когда script запускал цикл while и timer), в то время как файл temp db journal все еще был открыт. Windows не убивает процесс, даже если вы его убили в Python, независимо от того, используете ли вы db.close() или завершите работу в script; если вы выйдете из всех приложений Python, все еще будет работать в диспетчере задач.

Следовательно, вам нужно будет завершить все процессы Python в диспетчере задач Windows, перезапустить их, и это должно быть хорошо (если это на самом деле является причиной проблемы).

Ответ 8

У меня была такая же проблема некоторое время назад. Я попытался скопировать файл базы данных сам, переименовал его в другое имя файла, а затем проверил - он действительно РАБОТАЕТ!

Я использую SQLite3.

Я надеюсь, что это тоже сработает для вас!