我在我的iOS应用程序中使用SQLite,当用户与UI交互时,我有很多保存/加载。这是一个问题,因为它使UI非常紧张和缓慢。
我已尝试在另一个线程中执行操作,但我不认为这在SQLite中是可行的。如果我这样做,我会经常收到错误代码SQLITE_BUSY和SQLITE_LOCKED。
有没有办法在没有这些错误代码的多线程中执行此操作,还是应该放弃SQLite?
答案 0 :(得分:3)
完全有可能,您只需要在后台线程中序列化对SQLite的访问。
我对this recent question的回答应该指出我想的正确方向。
正如其他地方所提到的,SQLite适用于并发读取,但在数据库级别锁定以进行写入。这意味着如果你在不同的线程中读写,你将得到SQLITE_BUSY和SQLITE_LOCKED错误。
避免这种情况的最基本方法是在调度队列或具有1的并发性的NSOperationQueue
中序列化所有数据库访问(读取和写入)。没有在主线程上发生,您的UI不会受到影响。
这显然会停止读写重叠,但也会停止同时读取。目前尚不清楚这是否会影响您的表现。
如上所述初始化队列:
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue setMaxConcurrentOperationCount:1];
然后您可以根据需要向队列添加操作。
答案 1 :(得分:2)
将所有内容都放在专用的SQLite线程中,或者一次操作一个操作队列是很好的解决方案,尤其是解决您的抖动UI。另一种技术(可能无助于抖动)是发现这些错误代码,并简单地循环,重试更新,直到您获得成功的返回代码。
答案 2 :(得分:1)
将SQLite置于WAL模式。然后读取不会被阻止。不是这样写 - 你需要序列化它们。有多种方法可以实现它。其中一个是由SQLite提供的 - WAL钩子可以用来表示下一次写入可以启动。
WAL模式通常应该可以提高应用的性能。大多数事情都会快一些。读取不会被阻止。只有大型交易(几MB)才会放缓。一般没什么戏剧性的。
答案 3 :(得分:0)
不要放弃SQLite。您绝对可以在与 UI 线程不同的线程中执行此操作,以避免缓慢。只需确保一个线程一次只能访问数据库。在处理并发访问时,SQLite并不是很好。
答案 4 :(得分:0)
OFF:
你有结帐:FMDB它是一个sqlite Wrapper并且是线程安全的。我在我所有的sqlite项目中都使用过它。
答案 5 :(得分:0)
我建议使用位于sqlite之上的Core Data。我在多线程环境中使用它。这是Concurrency with Core Data的指南。