我正在编写的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
语句,以期解决问题。如果我注释掉其中任何一种方法,我都不会收到此错误。
有谁知道什么是错的?
答案 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不提供任何类型的“锁定等待”机制。
您的基本选择是:
答案 3 :(得分:3)
您的数据库已打开。使用sqlite3_close(db)
关闭它。
如果你没有关闭,那么访问你的数据库的进程将运行后台,这将导致数据库被锁定错误。
答案 4 :(得分:3)
如果您尝试sqlite3_close(DB)
,可能是因为您的方法试图同时访问同一个数据库。
尝试放置这行代码
sqlite3_busy_timeout(DB, 500);
介于sqlite3_open
和sqlite3_prepare_v2
之间的某个方法中,您获取"数据库已锁定" - 错误消息。
该方法中的数据库连接将在放弃之前500毫秒内尝试写入/读取,这通常足以逃脱锁定。
答案 5 :(得分:0)
首先,在打开新连接之前,您没有使用sqlite3_close()关闭数据库连接
答案 6 :(得分:0)
我只花了一个小时同样的问题。当我通过关闭shell(当脚本运行while循环和计时器时)无意中杀死进程时,我出现了问题,同时仍然打开了db日志临时文件。即使您已经在Python中杀死了它,Windows也不会终止进程,无论您是否在脚本中使用了db.close()或finalize;如果退出所有Python应用程序,仍然会在任务管理器中运行一个。
因此,您需要在Windows任务管理器中结束所有Python进程,重新启动它们,它应该没问题(如果实际上是问题的原因)。
答案 7 :(得分:-2)
前一段时间我遇到了同样的问题。我尝试复制数据库文件本身,将其重命名为不同的文件名,然后检查它 - 它实际上工作了!
我正在使用SQLite3。
我希望这对你也有用!