【问题标题】:SQLite3 do not always work properly (cannot prepare or execute queries)SQLite3 并不总是正常工作(无法准备或执行查询)
【发布时间】:2016-12-10 20:43:03
【问题描述】:

我正在使用 MacMini 进行 swift 开发,我正在 iPhone 6S 上进行测试。

我尝试安装 Sqlite-wrappers(SQLite.swift、fmdb),但它们都在启动时使我的应用程序崩溃。所以我使用纯 sqlite3-API。

起初,我创建了一个指向数据库的指针,并将其作为静态变量提供。

static var db: OpaquePointer? = nil
.....
sqlite3_open(fileURL.path, &db)

但我有时会遇到 Bad_Access 崩溃。搜遍了网络。发现“不要在不同线程中使用 1 个指针”。

所以现在我在需要它的时候用 open-statement 在不同的线程中创建一个指针,总是执行 sqlite3_reset、finalize 然后我关闭它。

static func getDBPointer() -> OpaquePointer? {
    var db: OpaquePointer? = nil
    if sqlite3_open(dbFile, &db) != SQLITE_OK {
        print("error opening database")
    } else {
        print("******************* DB opened")
    }
    return db
}

工作了几天,没有问题,没有 Bad_Access。

但是现在所有的数据库都表现得很奇怪。 它工作了一分钟,然后我无法插入或更新行,下一条语句再次正常工作。 “从表中删除*”在大多数情况下没有问题,但偶尔会失败。所有 sqlite3_prepare_v2() 语句都运行良好,我看不到语法问题。 在下一次尝试(相同的语句,所有格式正确,数据正确)我几乎总是“准备失败......”

这里是一个简短的代码示例:

let db = getDBPointer()

let insertStatementString = "INSERT INTO vorstellung_info (vorstellung_nr,datum,vorstellung,haus,autor) VALUES (\(vorst_num),\(vorst_datum),'\(vorstellung_name)','\(vorst_haus)','\(vorst_autor)');"

print("Insert vorstellung string: \(insertStatementString)")

var insertStatement: OpaquePointer? = nil

if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
    if sqlite3_step(insertStatement) == SQLITE_DONE {
        print("Done well.")
    } else {
        print("Could not insert row in vorstellung_info: \(insertStatementString)")
    }
} else {
    print("INSERT statement to vorstellung_info could not be prepared.")
}
sqlite3_finalize(insertStatement)
sqlite3_close_v2(db)

输出:

Insert vorstellung string: INSERT INTO vorstellung_info (vorstellung_nr,datum,vorstellung,haus,autor) VALUES (45127,1481382000000,'TEST-WantToSee','Thats the place','Interesting author');
Could not insert row in vorstellung_info: INSERT INTO vorstellung_info (vorstellung_nr,datum,vorstellung,haus,autor) VALUES (45127,1481382000000,'TEST-WantToSee','Thats the place','Interesting author');

正如我之前所说:有时甚至准备语句也会失败。

本例的创建表语句:

let createVorstellungInfo = "CREATE TABLE IF NOT EXISTS vorstellung_info(" +
            "vorstellung_nr INT," +
            "datum INT," +
            "vorstellung TEXT," +
            "haus TEXT," +
        "autor TEXT);"

程序通过会话与服务器进行大量“对话”,因此大多数非选择语句在 session.task 或由此类任务调用的静态函数中是异步的。

编辑:

将“String(cString: sqlite3_errmsg(db))”添加到任何可能的位置

“无法准备”:

SELECT statement could not be prepared: SELECT * from rechnung_vorst where rechnung_nr = 9868681 AND vorstellung_nr = 45138;
------------------------- 
database is locked

“无法加载”

Veranstalter could not get loaded: SELECT veranstalter_nname, veranstalter_vname, veranstalter_uid, veranstalter_ort, veranstalter_plz, veranstalter_str FROM veranstalter WHERE veranstalter_nr = 2062491;
------------------------- 
unknown error

这些只是几十条消息中的两个示例。 顺便说一句:我花了 4 - 5 次尝试来获取这些消息(一次尝试)。首先它工作正常,然后出现这些错误,然后它再次工作......

【问题讨论】:

标签: ios swift sqlite


【解决方案1】:

多线程 SQLite 很难。这很有趣,我永远不会说你不应该尝试自己解决这个挑战。但如果你想把时间花在其他地方,我建议你看看GRDB.swift。它提供了比其他库更多的并发保证:http://github.com/groue/GRDB.swift#concurrency

【讨论】:

    猜你喜欢
    • 2014-10-30
    • 1970-01-01
    • 2016-08-29
    • 2012-04-22
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多