有问题的读取提交行为 - 我应该期待什么?

问题描述 投票:0回答:1

关于使用 Wildfly、hibernate jpa、jta 和隔离级别 READ_COMMITED 的隔离级别的小简化问题。假设以下场景:

  1. 线程 1,在表 SomeTable 上,使用带有新事务的 JPA,更新特定实体属性(数据库中的单行)
  2. 线程 2,在表 SomeTable 上,使用 JPA 进行不同的事务,在提交事务 #1 之前,执行 findAll (select *)。

我的问题是:从事务隔离的角度(READ_COMMITED)。期望什么:

a) 线程 2 阻塞读取操作,直到线程 1 提交

b) 线程 2 能够无阻塞地读取,当然,还可以获取除线程 1 尚未提交的数据之外的所有数据

我认为选项 b 是正确的,因为这就是我心目中的隔离的含义。 但是,我遇到了 2 个数据库/驱动程序实现,第一个实现了我在选项 a 中描述的内容,第二个实现了选项 b。 所以我有点困惑,不确定这里是否有强制行为,而一个数据库只是有一个错误。 感谢您的评论!

hibernate wildfly jta transaction-isolation postgresql-15
1个回答
0
投票

根据 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_READ
or
SERIALIZABLE
level 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`方法。

© www.soinside.com 2019 - 2024. All rights reserved.