sqlite错误数据库已被锁定

cod*_*der 4 database sqlite iphone

我正在写的iPhone应用程序中有一个sqlite数据库.我在后台线程中运行以下代码时收到错误.在后台线程中,我调用此方法:

 - (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;
}
Run Code Online (Sandbox Code Playgroud)

然后我称这个方法:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

如果我一个接一个地运行这两个方法,我会收到一个错误,表明数据库已被锁定.我sqlite3_finalize在围绕谷歌寻找之后添加了这些声明,希望能解决这个问题.如果我注释掉其中任何一种方法,我都不会收到此错误.

有谁知道什么是错的?

Sau*_*abh 11

使用后必须始终关闭sqlite数据库...所以在此sqlite3_close(DB);之后添加此行sqlite3_finalize(statement);

更新 -

你在一个while循环中返回YES -

        while (sqlite3_step(statement) == SQLITE_ROW)
        {
            return YES;
            break;
        }
Run Code Online (Sandbox Code Playgroud)

所以在这里你不是最终确定也不是关闭数据库..你需要在每次打开它时关闭


Hot*_*cks 6

但请注意,如果您从多个线程访问同一个 SQLite DB,而没有某种单独的同步(通过某种方式知道您永远不会从多个线程进行近乎同步的访问),那么您可能会遇到“数据库锁定”的情况即使您在每次访问时正确关闭所有内容,也会出现错误。

SQLite 不提供任何类型的“锁等待”机制。

您的基本选择是:

  1. 从一个线程执行所有访问。
  2. 对所有访问使用单独的锁定协议。
  3. 如果出现“数据库已锁定”错误,请稍等片刻,然后重试。


小智 5

你的数据库是打开关闭它使用sqlite3_close(db)如果你不关闭那么访问你的数据库的进程将运行后台,这将导致数据库被锁定错误.

如果要删除数据库已锁定错误,请按照以下步骤操作:1.将数据库文件复制到其他位置.2.然后用复制的数据库替换数据库3.这将取消引用正在访问数据库文件的所有进程


tur*_*ted 5

如果您尝试过,sqlite3_close(DB)可能是因为您的方法试图同时访问同一个数据库。试试这行代码

sqlite3_busy_timeout(DB, 500);
Run Code Online (Sandbox Code Playgroud)

介于sqlite3_open和 之间sqlite3_prepare_v2的某个地方,您会收到“数据库已锁定”错误。

然后,数据库连接将在放弃之前的 500 毫秒内尝试写入/读取,这通常足以逃脱锁定。