2

我在 iOS 应用程序中删除我在 SQLite 中创建的索引时遇到了一些麻烦。我正在使用fmdb

尝试删除索引时,sqlite3_step始终返回SQLITE_LOCKED. 结果,fmdb 陷入无限循环,它不断尝试重试 drop 语句(每次都sqlite3_step返回SQLITE_LOCKED),并且该语句永远不会成功。

据我所知,在 drop 语句正常工作之前,没有其他进程接触数据库和语句。我错过了什么?

这几乎是失败代码的逐字副本:

[db open];
/* ... */
[db executeUpdate:@"DROP INDEX IF EXISTS bookmark_hash_idx;"];
[db close];

db是指向我的文档目录中的 sqlite 数据库的指针。

这是来自 fmdb 的相关代码,如果有用的话:

do {
    rc      = sqlite3_step(pStmt);
    retry   = NO;

    if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
        // this will happen if the db is locked, like if we are doing an update or insert.
        // in that case, retry the step... and maybe wait just 10 milliseconds.
        retry = YES;
        if (SQLITE_LOCKED == rc) {
            rc = sqlite3_reset(pStmt);
            if (rc != SQLITE_LOCKED) {
                NSLog(@"Unexpected result from sqlite3_reset (%d) eu", rc);
            }
        }
        /* ... */
    }
    /* ... */
} while (retry);
4

1 回答 1

6

您可能有打开的结果集阻止 DROP INDEX 通过。来自 SQLite文档

“删除表”异常

当调用 sqlite3_step() 返回 SQLITE_LOCKED 时,调用 sqlite3_unlock_notify() 几乎总是合适的。然而,有一个例外。在执行“DROP TABLE”或“DROP INDEX”语句时,SQLite 检查当前是否有任何正在执行的 SELECT 语句属于同一连接。如果有,则返回 SQLITE_LOCKED。在这种情况下,没有“阻塞连接”,因此调用 sqlite3_unlock_notify() 会导致立即调用 unlock-notify 回调。如果应用程序随后重新尝试“DROP TABLE”或“DROP INDEX”查询,则可能会导致无限循环。

您应该调用closeOpenResultSets您的FMDatabase对象以确保在删除索引之前关闭所有打开的结果集。

于 2013-05-27T08:19:07.030 回答