我在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条答案
按热度按时间bttbmeg01#
你必须总是关闭sqlite数据库后使用它.所以在
sqlite3_finalize(statement);
之后添加这行sqlite3_close(DB);
更新-
在while循环中返回YES
所以在这里你既没有完成也没有关闭数据库..你需要关闭,如果每次你打开它
4si2a6ki2#
但是请注意,如果您从多个线程访问同一个SQLite DB,而没有某种单独的同步(某种方法可以知道您永远不会有来自多个线程的近乎同时的访问),那么即使您在每次访问时正确关闭所有内容,也可能会出现“数据库锁定”错误。
SQLite不提供任何类型的“锁等待”机制。
您的基本选项包括:
1.从一个线程执行所有访问。
1.对所有访问使用单独的锁协议。
1.如果你得到一个“数据库锁定”错误,等待一段时间,然后重试。
2lpgd9683#
你的数据库是打开关闭它使用sqlite3_close(db)如果你不关闭然后访问你的数据库的进程将运行后台这将导致数据库被锁定错误.
如果你想删除数据库被锁定错误,请按照以下步骤操作1.将数据库文件复制到其他位置。2.然后用复制的数据库替换数据库3.这将取消引用所有访问数据库文件的进程
ekqde3dh4#
如果你尝试过
sqlite3_close(DB)
,那可能是因为你的方法试图同时访问同一个数据库。试试这行代码在
sqlite3_open
和sqlite3_prepare_v2
之间的某个地方,从那里你得到“数据库被锁定”-错误。数据库连接将在500毫秒内尝试写/读,然后放弃,这通常是足够的时间来摆脱锁定。
af7jpaap5#
您的数据库已打开。使用
sqlite3_close(db)
关闭它。如果不关闭,那么访问数据库的进程将在后台运行,这将导致数据库被锁定错误。
gmxoilav6#
首先,在打开一个新连接之前,您没有使用sqlite3_close()关闭数据库连接
ars1skjm7#
我刚花了一个小时解决同样的问题。当我无意中关闭shell杀死一个进程时(当脚本运行while循环和计时器时),问题就出现了,而数据库日志临时文件仍然打开。Windows不会杀死进程,即使你在Python中杀死了它,不管你在脚本中使用了db.close()还是finalize;如果你退出所有的Python应用程序,任务管理器中仍然会有一个运行。
因此,您需要在Windows任务管理器中结束所有Python进程,重新启动它们,应该没问题(* 如果 * 这实际上是问题的原因)。
bwntbbo38#
不久前我也有同样的问题。我试着复制数据库文件本身,将其重命名为不同的文件名,然后检查它-它实际上工作!
我用的是SQLite3。
我希望这也能为你工作!