Iphone sqlite错误数据库已锁定
我正在编写的iPhone应用程序中有一个sqlite数据库。我在后台线程中运行的以下代码出现错误。在后台线程中,我将此方法称为:Iphone sqlite错误数据库已锁定,iphone,database,sqlite,Iphone,Database,Sqlite,我正在编写的iPhone应用程序中有一个sqlite数据库。我在后台线程中运行的以下代码出现错误。在后台线程中,我将此方法称为: - (BOOL) songIsInDatabase:(NSString *)songTitle { NSString *docsDir; NSArray *dirPaths; dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); doc
- (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];
}
然后我把这个方法叫做:
- (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\u finalize
语句,希望能解决这个问题。如果我注释掉这两种方法中的任何一种,我不会得到这个错误
有人知道出了什么问题吗?首先,在打开新连接之前,不能使用sqlite 3\u close()关闭数据库连接在使用sqlite数据库之后,必须始终关闭它。。。因此,添加这一行
sqlite3\u close(DB)代码>紧接着sqlite3\u完成(语句)代码>
更新-
您在while循环中返回YES-
while (sqlite3_step(statement) == SQLITE_ROW)
{
return YES;
break;
}
因此,在这里您将无法完成或关闭数据库。。如果每次打开它时都需要关闭,但是请注意,如果您从多个线程访问同一个SQLite DB,而没有某种单独的同步(某种方式可以知道您永远不会有来自多个线程的几乎同时的访问),那么很可能会“锁定数据库”即使在每次访问时正确关闭了所有内容,也会出现错误
SQLite不提供任何类型的“锁定等待”机制
您的基本选择是:
从一个线程执行所有访问
对所有访问使用单独的锁定协议
如果出现“数据库锁定”错误,请稍等片刻,然后重试
您的数据库已打开,请使用sqlite3\u close(db)关闭它
如果不关闭,则访问数据库的进程将在后台运行
这将导致数据库被锁定错误
如果要删除数据库被锁定错误,请执行以下步骤
1.将数据库文件复制到其他位置。
2.然后用复制的数据库替换数据库
3.这将取消对访问数据库文件的所有进程的引用,因为数据库已打开。使用sqlite3\u Close(db)
将其关闭
如果不关闭,则访问数据库的进程将在后台运行,这将导致数据库被锁定错误。我刚刚花了一个小时处理相同的问题。当我关闭shell(当脚本运行while循环和计时器时),而db journal temp文件仍然打开时,无意中杀死了一个进程,这就产生了我的问题。Windows不会终止进程,即使您在Python中终止了进程,无论您在脚本中使用了db.close()还是finalize;如果退出所有Python应用程序,任务管理器中仍将有一个应用程序在运行
因此,您需要在Windows任务管理器中结束所有Python进程,重新启动它们,这样就可以了(如果这确实是问题的原因的话) 如果您尝试了sqlite3\u close(DB)
,可能是因为您的方法试图同时访问同一个数据库。
尝试放置这行代码
sqlite3_busy_timeout(DB, 500);
在获取“数据库已锁定”的方法中,介于sqlite3\u open
和sqlite3\u prepare\u v2
之间的某个位置
然后,该方法中的数据库连接将在放弃之前的500毫秒内尝试写入/读取,这通常是足够的时间来逃避锁定。我刚才也遇到过同样的问题。我尝试复制数据库文件本身,将其重命名为不同的文件名,然后检查它-它实际上起作用了
我正在使用SQLite3
我希望这对你也有用 我发现,当我使用sqlite3_reset时,即使不关闭数据库,也不会出现数据库锁定错误。在每次准备之后使用sqlite3_reset语句,这样它将重置准备好的语句。这将解决您的数据库被锁定错误。这不是sqlite中的“锁定等待”机制吗@DmitryPashkevich-在标准SQLite中没有可靠的内置锁定机制。他们所做的仅仅是为了在出现代码错误的情况下保护数据库的完整性,也许还能够实现某种粗略的恢复。那么,上述功能不能正常工作?我不应该依赖它?但是它就在那里?@DmitryPashkevich-它做了它想要做的事情,即保护数据库并防止死锁。然而,对于一般情况,它不是一个足够的锁定机制。特别是,您将在事务中遇到很多问题。