Ios Sqlite数据库在执行时被锁定";完";
为了加快在iOS6上的sqlite3db上的DB插入,我将插入内容包装在“BEGIN”和“END”命令中。 数据库设置为以序列化模式运行。 有趣的是,我在执行“END”时遇到了一个异常:错误表示数据库被锁定。 嗯,我希望它会被锁定,毕竟据我所知,我正在进行交易。Ios Sqlite数据库在执行时被锁定";完";,ios,sqlite,xamarin.ios,Ios,Sqlite,Xamarin.ios,为了加快在iOS6上的sqlite3db上的DB插入,我将插入内容包装在“BEGIN”和“END”命令中。 数据库设置为以序列化模式运行。 有趣的是,我在执行“END”时遇到了一个异常:错误表示数据库被锁定。 嗯,我希望它会被锁定,毕竟据我所知,我正在进行交易。 有人能解释一下什么条件会导致这种行为吗?这必须很简单,因为BEGIN/END命令没有什么特别之处。我试图重现您的问题(消除sqlite3\u finalize,消除BEGIN,等等),但我做不到。我知道生成该错误的唯一方法是多次打开数据
有人能解释一下什么条件会导致这种行为吗?这必须很简单,因为BEGIN/END命令没有什么特别之处。我试图重现您的问题(消除
sqlite3\u finalize
,消除BEGIN
,等等),但我做不到。我知道生成该错误的唯一方法是多次打开数据库或使用后台队列执行某些操作
您必须与我们共享源代码。也许您正试图重新打开数据库?或者你的后台队列中有什么东西可能会容纳它?等等
您提到以串行模式打开数据库。我是否可以推断您有多个队列/线程执行数据库操作?我个人通过一个串行队列来序列化我的数据库操作,我将数据库调用分派到该队列,这保证了串行操作,因此我不必担心以特定模式打开数据库。也许您可以描述以串行模式打开数据库的基本原理
但是,无论如何,这里有一个直接使用sqlite
调用的示例insert方法(尽管我承认我通常使用它来消除像这样难看的代码):
我发现了问题。要使序列化访问正常工作,您只能有一个连接。在我的测试项目中,我忘记实现连接缓存。这样,每个数据库都有相当多的(开放的)连接。我确实有多个线程。但在那个特定的时刻,只有一个线程处于活动状态。因此出现了序列化模式。我还在所有地方共享相同的连接,否则序列化将无法工作。我用不同的线程敲打DB来测试序列化,它是防弹的。如果我切换到默认模式,它会按预期失败。我已经运行这段代码很长时间了,今天它开始挂起,所以我想知道Sqlite中是否有明显的东西会导致这个问题。看来我得再深入一点。@Krumelur是的,如果你从不同的线程中敲打,而没有(a)数据库操作的专用队列;或者(b)使用序列化模式,您会遇到问题。我只是想知道,如果您依赖于数据库的序列化模式,那么三个单独的调用,
begin
、insert
、和end
,是否被视为三个单独的语句,可以与来自其他线程的其他数据库调用进行序列化(错误)。如果您目前只使用一个线程,那么这不是问题所在。但是,通过为数据库操作提供一个专用队列,这个问题就消失了。
- (void)sqlInsert
{
sqlite3_stmt *statement;
sqlite3 *database = NULL;
int rc;
char *errmsg;
if ((rc = [self openDatabase:&database]) != SQLITE_OK) // my open does the necessary parsing of the path, copying files, etc.
{
NSLog(@"%s database open error %d", __FUNCTION__, rc);
return;
}
sqlite3_exec(database, "BEGIN", NULL, NULL, &errmsg);
if (errmsg != NULL)
{
NSLog(@"%s exec BEGIN SQL error '%s'", __FUNCTION__, errmsg);
sqlite3_free(errmsg);
}
const char *insertSql = "INSERT INTO CONTACTS (name, address, phone) VALUES (?, ?, ?)";
if (sqlite3_prepare_v2(database, insertSql, -1, &statement, NULL) != SQLITE_OK)
NSLog(@"%s prepare SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
if (sqlite3_bind_text(statement, 1, [self.contactName.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"%s bind contactName error '%s'", __FUNCTION__, sqlite3_errmsg(database));
if (sqlite3_bind_text(statement, 2, [self.contactAddress.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"%s bind contactAddress error '%s'", __FUNCTION__, sqlite3_errmsg(database));
if (sqlite3_bind_text(statement, 3, [self.contactPhone.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"%s bind contactPhone error '%s'", __FUNCTION__, sqlite3_errmsg(database));
if (sqlite3_step(statement) == SQLITE_DONE)
NSLog(@"%s Contact added", __FUNCTION__);
else
NSLog(@"%s step SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));
sqlite3_finalize(statement);
sqlite3_exec(database, "END", NULL, NULL, &errmsg);
if (errmsg != NULL)
{
NSLog(@"%s exec END SQL error '%s'", __FUNCTION__, errmsg);
sqlite3_free(errmsg);
}
sqlite3_close(database);
}