使用多线程读取 FMDB 数据库
Posted
技术标签:
【中文标题】使用多线程读取 FMDB 数据库【英文标题】:FMDB database read using multithreading 【发布时间】:2016-11-18 07:07:12 【问题描述】:我在 ios 中为 sqlite 使用 FMDB 数据库库。如何在 FMDB 中同时执行多个读取操作。目前我正在使用 FMDB 数据库队列。
【问题讨论】:
【参考方案1】:FMDatabaseQueue 序列化所有数据库访问。 FMDatabaseQueue 不能同时执行多个读取操作,而且永远不会:这不是 FMDatabaseQueue 的目的。
不幸的是,FMDB 不提供任何其他安全的并发模型。您可以使用原始 FMDatabase 连接,并自己处理写入序列化和并行读取。例如,您可以将数据库调用包装在并发 DispatchQueue 中:
let dbQueue = DispatchQueue(label: "database", attributes: .concurrent)
func read(block: () -> ())
// Since the queue is concurrent, several readers can execute at
// the same time.
dbQueue.sync(execute: block)
func write(block: () -> ())
// The barrier flag makes sure that only one writer block is executing
// at a given time, and that no reader is currently executing.
dbQueue.sync(flags: .barrier, execute: block)
let db = FMDatabase(...)
read
// Select from db
write
// Write in db
不过,此解决方案有一些注意事项:并发读取的数量不受限制,您不会从围绕事务或保存点的 DatabaseQueue 高级 API 中受益,并且read
方法不会阻止您执行数据库更新。
您可以查看 FMDB 的替代方案:GRDB.swift 库。它与 FMDB 非常相似。不过,与 FMDB 不同的是,它提供了一个 DatabasePool 类,可以避免上面列出的所有警告:https://github.com/groue/GRDB.swift#database-pools
let dbPool = DatabasePool(path: ...)
// Serialized writes
try dbPool.write db in
try db.execute("CREATE TABLE ...")
try db.execute("INSERT INTO ...")
// Concurrent reads
dbPool.read db in
for row in Row.fetch(db, "SELECT * FROM ...")
...
let count = Int.fetchOne(db, "SELECT COUNT(*) FROM ...")!
【讨论】:
FMDB也有DatabasePool,有什么用? FMDB 的 DatabasePool 与 GRDB 的 DatabasePool 完全不同,尽管它们的名称相同。 FMDB DatabasePool 是dangerous,而 GRDB DatabasePool 是坚如磐石的。【参考方案2】:FMDB 队列适用于多线程。目前我在多线程应用程序中使用它,没有发现任何问题。
请描述您在使用 FMDB 队列时遇到的问题
示例
var queue = FMDatabaseQueue(path:"db path")
queue.inTransaction (db, rollback) in
do
let resultset = try db.executeQuery(queryString, values: [])
while(resultset.next())
//do your task
catch
rollback.memory = true
print(error)
【讨论】:
【参考方案3】:检查此链接对您有用:
http://www.theappguruz.com/blog/use-sqlite-database-swift
获取数据:
@IBAction func findContact(_ sender: AnyObject) let contactDB = FMDatabase(path: databasePath as String)
if (contactDB?.open())!
let querySQL = "SELECT address, phone FROM CONTACTS WHERE name = '\(name.text!)'"
let results:FMResultSet? = contactDB?.executeQuery(querySQL,
withArgumentsIn: nil)
if results?.next() == true
address.text = results?.string(forColumn: "address")
phone.text = results?.string(forColumn: "phone")
status.text = "Record Found"
else
status.text = "Record not found"
address.text = ""
phone.text = ""
contactDB?.close()
else
print("Error: \(contactDB?.lastErrorMessage())")
【讨论】:
以上是关于使用多线程读取 FMDB 数据库的主要内容,如果未能解决你的问题,请参考以下文章