sqlite错误数据库已被锁定

时间:2012-01-13 16:36:12

标签: iphone database sqlite

我正在编写的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;
}

然后我称之为这个方法:

- (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语句,以期解决问题。如果我注释掉其中任何一种方法,我都不会收到此错误。

有谁知道什么是错的?

8 个答案:

答案 0 :(得分:11)

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

更新 -

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

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

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:3)

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

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

您的基本选择是:

  1. 从一个线程进行所有访问。
  2. 围绕所有访问使用单独的锁定协议。
  3. 如果出现“数据库锁定”错误,请等待一段时间,然后重试。

答案 3 :(得分:3)

您的数据库已打开。使用sqlite3_close(db)关闭它。

如果你没有关闭,那么访问你的数据库的进程将运行后台,这将导致数据库被锁定错误。

答案 4 :(得分:3)

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

sqlite3_busy_timeout(DB, 500);

介于sqlite3_opensqlite3_prepare_v2之间的某个方法中,您获取"数据库已锁定" - 错误消息。

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

答案 5 :(得分:0)

首先,在打开新连接之前,您没有使用sqlite3_close()关闭数据库连接

答案 6 :(得分:0)

我只花了一个小时同样的问题。当我通过关闭shell(当脚本运行while循环和计时器时)无意中杀死进程时,我出现了问题,同时仍然打开了db日志临时文件。即使您已经在Python中杀死了它,Windows也不会终止进程,无论您是否在脚本中使用了db.close()或finalize;如果退出所有Python应用程序,仍然会在任务管理器中运行一个。

因此,您需要在Windows任务管理器中结束所有Python进程,重新启动它们,它应该没问题(如果实际上是问题的原因)。

答案 7 :(得分:-2)

前一段时间我遇到了同样的问题。我尝试复制数据库文件本身,将其重命名为不同的文件名,然后检查它 - 它实际上工作了!

我正在使用SQLite3。

我希望这对你也有用!