进程间SQLite线程安全(在iOS上)

我试图确定如果我的SQLite访问数据库是在iOS上线程安全的。 我正在编写一个非App Store应用程序(或可能是一个启动守护程序),所以苹果的批准不是问题。 有问题的数据库是内置的sms.db ,所以肯定操作系统也访问这个数据库的读写。 我只想能够安全地阅读它。

我读过这个关于阅读从多个进程与SQLite :

多个进程可以同时打开同一个数据库。 多个进程可以同时做一个SELECT。 但是,只有一个进程可以随时对数据库进行更改。

我明白,线程安全可以从sqlite编译出来,而sqlite3_threadsafe()可以用来testing这个。 在iOS 5.0.1上运行

 int safe = sqlite3_threadsafe(); 

产生2的结果。 据此 ,这意味着互斥锁可用 。 但是,这并不意味着它正在使用。

我并不完全清楚线程安全是在每个连接,每个数据库还是全局基础上dynamic启用的。

我也读过这个 。 看起来像sqlite3_config()可以用来启用安全的multithreading,但是当然,我没有控制权,或者操作系统本身可能如何使用这个调用(我?)的可见性。 如果我在应用程序中再次进行调用,是否会安全地读取数据库,还是只能解决使用相同sqlite3数据库句柄的应用程序中多个线程的并发访问冲突?

无论如何,我的问题是…

我可以安全地阅读这个数据库,也可以通过iOS访问,如果是的话,如何?

我从来没有使用过SQLite,但是我花了相当多的时间阅读它的文档,因为我打算将来使用它(而且文档很有趣)。 我想说,线程安全是独立于多个进程是否可以同时访问同一个数据库文件。 无论SQLite处于什么线程模式,SQLite都会locking数据库文件 ,以便多个进程可以一次从数据库读取,但只能写入一个。

线程安全只影响你的进程如何使用SQLite。 没有任何线程的安全性,你只能从一个线程调用SQLite函数。 但是在编写之前还应该先取得一个EXCLUSIVElocking,以便其他进程不会破坏数据库文件。 如果使用multithreading,线程安全只是保护进程内存中的数据免受损坏。 所以我不认为你需要担心另一个进程(在这种情况下,iOS)是用SQLite数据库做什么的。

编辑:为了澄清,任何时候你写入数据库,包括一个纯粹的INSERT / UPDATE / DELETE ,它会自动采取一个EXCLUSIVE锁,写入数据库,然后释放锁。 (实际上它需要一个SHARED锁,然后是一个RESERVED锁,然后是一个PENDING锁,然后在写入之前使用一个EXCLUSIVE锁。)默认情况下,如果数据库已经被locking(来自另一个进程),那么SQLite将不返回SQLITE_BUSY 。 你可以调用sqlite3_busy_timeout()来告诉它等待更长的时间。

我不认为这是你的新闻,但有一些想法:

在启用multithreading(序列化或multithreading)方面,一般的法律是可以调用sqlite3_config() (但是你可能必须首先按照文档中的build议或者这里讨论的那样closures)启用你想要的那种multithreading。 但是,在这里你可能无法控制iOS所要求的sqlite和/或这个数据库。

因此,我想从学术的angular度来看,阅读这个系统数据库是不安全的(因为正如你所说,你不能确定操作系统在做什么)。 但是,如果iOS使用默认模式打开数据库,我不会感到惊讶,所以从更实际的angular度来看,你可能会好起来的。

显然,对于大多数关心单个应用程序中的multithreading访问的用户来说,最好的build议是绕过sqlite3_config()恶意程度,只是简单地确保通过自己的GCD串行队列进行协调访问(即拥有一个专用的队列,数据库交互通过,完全消除multithreading问题)。 可悲的是,这不是一个选项,因为你正在试图协调数据库与iOS本身的交互。