我已经阅读了很多主题,但无法找出问题的答案:是否可以同时读写?
我有后台线程更新一些数据,UI需要存储在DB中的小块数据。因此在UI线程中执行SELECT操作。但它会在更新过程中阻止。结果,UI冻结了几秒钟。
写作时,有没有人能从DB中读取成功?
可以在iPhone上读写DB。这种差异的原因是在本机sqlite函数上同步实现包装吗?
答案 0 :(得分:55)
在Android 3.0及更高版本上,SQLiteDatabases支持WAL模式(预写日志记录):
如果未启用预写日志记录(默认值),则不是 可以在数据库上同时进行读取和写入 时间。在修改数据库之前,编写者隐式地获取了一个 数据库上的独占锁定,阻止读者访问 数据库直到写完成。
相反,当启用预写日志记录时,写入操作 发生在一个单独的日志文件中,允许继续读取 同时。写入正在进行中,读者在其他线程上 将在写入之前感知数据库的状态 开始了。当写完成时,其他线程上的读者将会 感知数据库的新状态。
要在WAL模式下启动事务,请使用beginTransactionNonExclusive()而不是beginTransaction()。 当beginTransaction()以EXCLUSIVE模式启动事务时,beginTransactionNonExclusive()以IMMEDIATE模式启动一个事务
简单来说:为IMMEDIATE模式调用beginTransactionNonExclusive(),我们可以在另一个线程正在写入时读取(写入事务开始之前的状态,因为我们不会使用read_uncommitted连接 - > http://en.wikipedia.org/wiki/Isolation_%28database_systems%29#Dirty_reads)。 / p>
答案 1 :(得分:3)
您无法同时阅读和书写。 SQLite是一个无服务器,基于文件的数据库。
“当任何进程想要写入时,它必须在更新期间锁定整个数据库文件。但这通常只需要几毫秒。其他进程只需等待编写器完成然后继续他们的业务。其他嵌入式SQL数据库引擎通常只允许单个进程一次连接到数据库。“
答案 2 :(得分:3)
从API 11开始,Android支持WAL模式。它在事务期间保持原始数据不变,因此其他线程可以在事务运行时读取。您可以查看我的文章,了解有关WAL模式的更多详细信息:
http://www.skoumal.net/en/parallel-read-and-write-in-sqlite/
您还应该避免在UI线程中运行数据库查询。它总是会变得迟钝并阻止你的用户界面。
答案 3 :(得分:1)
无法阅读&同时写。但是,如果您正确设置了SQLite数据库类(数据库和辅助类的单个实例),则不同的线程应该能够同步获取数据库连接,以便没有任何明显的延迟。
听起来你正试图用你的UI线程做后端工作(写入数据库)。你不应该这样做。创建一个AsyncTask来处理它,而不是让你的UI线程处理它。
请参阅SQLiteOpenHelper文档。以下是关于此问题的上一篇文章:What are the best practices for SQLite on Android?