SQLite同时读写

时间:2011-11-12 13:49:51

标签: android database multithreading sqlite

我已经阅读了很多主题,但无法找出问题的答案:是否可以同时读写?

我有后台线程更新一些数据,UI需要存储在DB中的小块数据。因此在UI线程中执行SELECT操作。但它会在更新过程中阻止。结果,UI冻结了几秒钟。

写作时,有没有人能从DB中读取成功?


可以在iPhone上读写DB。这种差异的原因是在本机sqlite函数上同步实现包装吗?

4 个答案:

答案 0 :(得分:55)

在Android 3.0及更高版本上,SQLiteDatabases支持WAL模式(预写日志记录):

  

如果未启用预写日志记录(默认值),则不是   可以在数据库上同时进行读取和写入   时间。在修改数据库之前,编写者隐式地获取了一个   数据库上的独占锁定,阻止读者访问   数据库直到写完成。

     

相反,当启用预写日志记录时,写入操作   发生在一个单独的日志文件中,允许继续读取   同时。写入正在进行中,读者在其他线程上   将在写入之前感知数据库的状态   开始了。当写完成时,其他线程上的读者将会   感知数据库的新状态。

     

http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#enableWriteAheadLogging()

要在WAL模式下启动事务,请使用beginTransactionNonExclusive()而不是beginTransaction()。 当beginTransaction()以EXCLUSIVE模式启动事务时,beginTransactionNonExclusive()以IMMEDIATE模式启动一个事务

  • EXCLUSIVE模式使用排他锁(http://www.sqlite.org/lockingv3.html#excl_lock),这意味着没有其他数据库连接,除了read_uncommitted连接将能够读取数据库,没有异常的其他连接将能够写入数据库,直到事务完成< / LI>
  • IMMEDIATE模式使用保留锁(http://www.sqlite.org/lockingv3.html#reserved_lock),这意味着没有其他数据库连接可以写入数据库或执行BEGIN IMMEDIATE或BEGIN EXCLUSIVE,但是其他进程可以继续从数据库读取。 / LI>

简单来说:为IMMEDIATE模式调用beginTransactionNonExclusive(),我们可以在另一个线程正在写入时读取(写入事务开始之前的状态,因为我们不会使用read_uncommitted连接 - &gt; http://en.wikipedia.org/wiki/Isolation_%28database_systems%29#Dirty_reads)。 / p>

答案 1 :(得分:3)

您无法同时阅读和书写。 SQLite是一个无服务器,基于文件的数据库。

来自SQLite FAQ:

“当任何进程想要写入时,它必须在更新期间锁定整个数据库文件。但这通常只需要几毫秒。其他进程只需等待编写器完成然后继续他们的业务。其他嵌入式SQL数据库引擎通常只允许单个进程一次连接到数据库。“

答案 2 :(得分:3)

从API 11开始,Android支持WAL模式。它在事务期间保持原始数据不变,因此其他线程可以在事务运行时读取。您可以查看我的文章,了解有关WAL模式的更多详细信息:

http://www.skoumal.net/en/parallel-read-and-write-in-sqlite/

您还应该避免在UI线程中运行数据库查询。它总是会变得迟钝并阻止你的用户界面。

答案 3 :(得分:1)

无法阅读&amp;同时写。但是,如果您正确设置了SQLite数据库类(数据库和辅助类的单个实例),则不同的线程应该能够同步获取数据库连接,以便没有任何明显的延迟。

听起来你正试图用你的UI线程做后端工作(写入数据库)。你不应该这样做。创建一个AsyncTask来处理它,而不是让你的UI线程处理它。

请参阅SQLiteOpenHelper文档。以下是关于此问题的上一篇文章:What are the best practices for SQLite on Android?