Android:SQLite(ORMLite)事务隔离级别

我在我的Android项目中使用ORMLite。 我知道Sqlite负责文件级锁定。 很multithreading都可以读,有人可以写。 锁可防止多次写入。 有人可以解释一下,如果一个线程正在更新某个记录而另一个线程正在尝试读取此记录,会发生什么? 线程(试图读取)会得到过时的数据吗? 或者它会被锁定,直到第一个线程完成其写操作? 据我所知,有4个事务隔离级别:Serializable,Repeatable read,Read committed,Read uncommitted。 有没有办法在SQLite或ORMLite中更改它?

SQLite有5个不同的锁级别 – http://www.sqlite.org/lockingv3.html:unlocked,shared,reserved,pending,exclusive 。 这个问题的重要锁定是共享锁:

“共享 – 数据库可以被读取但不能被写入。任意数量的进程可以同时保存SHARED锁,因此可以有许多同时读取。但是没有其他线程或进程可以写入数据库文件,而不是更多的SHARED锁是活跃的。“

锁是表级的(因此在DB中使用单行执行某些操作时 – 整个表都被锁定)。

因此,在选择数据时,不允许其他进程更改数据。 读取数据的锁定步骤为:UNLOCKED→PENDING→SHARED→UNLOCKED(您可以在事务中运行选择)。 因此,您选择某些内容并且某人将更改数据的情况不会发生。

您的问题是如果您要更新数据库并在同一个表上执行选择会发生什么。 在自动提交模式下,写入/更新的锁定机制为:UNLOCKED→PENDING→SHARED→RESERVED→PENDING→EXCLUSIVE→UNLOCKED。 在Exclusive锁中,没有新的读者(连接)可以连接到数据库。 一次只能存在一个EXCLUSIVE锁。 然后SQLite将等待,直到读取连接的所有其他PENDING锁被释放并且将阻止任何新的。 此时,它将开始写入数据。

所以,我的答案是 – 只要更新过程没有完成,你的其他过程当然会获得旧数据。 确保在事务中运行更新,以便不会发生数据的不一致。 SQLite符合ACID标准,因此不应发生部分更新和包含数据的情况。

一本关于此的好书是“SQLite的权威指南”,特别是“交易”一章。

SQLite支持几种不同的隔离级别,可在编译时和运行时选择。

http://www.sqlite.org/threadsafe.html

我假设Android的SQLite默认处于序列化模式。 在multithreading访问方面,它在文件系统级别执行读/写锁定以允许多个读取器,但一次只允许一个写入器:

http://www.sqlite.org/faq.html#q5

但是,ORMLite 强烈建议并努力维护与数据库的单个连接,因此锁定问题可能不相关。

更具体地说,如果一个线程正在更新记录而另一个线程正在读取,那么它就是竞争条件。 读取线程将在更新之前或更新完成之后获取记录。 但是,读者不会获得部分更新的数据。 但我怀疑你知道这一点。

就SQLite支持的隔离级别而言,默认为Serialized ,如上所述,但它看起来至少在某种程度上支持read-uncommitted

http://www.sqlite.org/sharedcache.html

您可以使用ORMLite的Dao.executeRaw()方法来启用它:

dao.executeRaw("PRAGMA read_uncommitted = True;"); 

但是,我对此没有任何经验,也不确定如果在同一查询中多次访问该行,它是否会为您提供更新行的一致视图。 在写入事务期间,它可能与更一致的视图有关。

在阅读了这个类似的问题之后 ,如果在同一个查询中多次访问它,我不确定是否可以保证表中行的相同视图。