关于使用 Wildfly、hibernate jpa、jta 和隔离级别 READ_COMMITED 的隔离级别的小简化问题。假设以下场景:
我的问题是:从事务隔离的角度(READ_COMMITED)。期望什么:
a) 线程 2 阻塞读取操作,直到线程 1 提交
b) 线程 2 能够无阻塞地读取,当然,还可以获取除线程 1 尚未提交的数据之外的所有数据
我认为选项 b 是正确的,因为这就是我心目中的隔离的含义。 但是,我遇到了 2 个数据库/驱动程序实现,第一个实现了我在选项 a 中描述的内容,第二个实现了选项 b。 所以我有点困惑,不确定这里是否有强制行为,而一个数据库只是有一个错误。 感谢您的评论!
根据 JDBC-4.3 规范 (JSR-221) 第 10.2 项的定义(我很确定它可以追溯到很久以前),将事务隔离定义为 TRANSACTION_READ_COMMITED 时的正确行为“意味着所做的任何更改在事务提交之前,事务内部在事务外部不可见”,什么会“防止脏读,但不可重复读和幻读仍然是可能的”。
当在事务之外读取未提交的更改时,就会发生脏读。当同一行的两次后续读取不同时,会发生不可重复读取,因为它们之间发生了提交。当不同的读取可能返回不同的行时,就会发生幻像读取。
回到你的描述,当使用
TRANSACTION_READ_COMMITED
作为事务隔离级别时,应该会导致“b”场景:线程 2 应该能够读取线程 1 提交之前存在的数据,如果再次尝试,应该读取新数据(可能是幻读),一切都没有阻塞。
“a”场景中描述的块行为仅应在隔离设置为
TRANSACTION_REPEATABLE_READ
(部分,仅针对同一行)或TRANSACTION_SERIALIZABLE
时发生。
根据规范,如果 JDBC 驱动程序不支持较轻的事务隔离,则应采用更高(限制性更强)的级别,如果不能,则抛出
SQLException. Probably this is the case with your first JDBC driver, that used a
REPEATABLE_READor
SERIALIZABLElevel when you set it to
READ_COMMITED . The spec does not mandates that the JDBC driver implementation reports this "upgrade" of level. You may test the supported isolation level using
支持TransactionIsolationLevel`方法。