我尝试理解READ COMMITED和READ UNCOMMITED隔离级别在Hibernate中的工作方式,需要一些解释。
有两个线程 THR1 和 THR2 都执行相同的事务方法(Spring Transactional注释,隔离级别设置为READ COMMITED)。创建的名称交易相应地是这些线程 TRA1 和 TRA2 。事务方法如下所示:
@RequestMapping(value = "/dentists", method = RequestMethod.GET)
public List<Dentist> search(@RequestParam("name") String name,
@RequestParam("city") String city,
@RequestParam("type") String type,
@RequestParam("rating") String rating) {
return dentistRepository.findDentistByName(name);
}
Preference类使用Entity注释(optimisticLock = OptimisticLockType.NONE)来强制执行此实体的2PL模型(我错了吗?)。我使用Oracle数据库。
请考虑以下情况:
让我们假设线程THR1步骤到第1行并查询对象。如果我理解正确,该线程创建的事务TRA1将获取查询的entiry的共享读锁。然后,如果THR2线程步骤到第3行尝试获取该实体的独占写锁定,那么THR2是否应该被阻塞,直到TRA1释放读锁定?
假设线程THR1步进第3行并获取实体的独占写锁(保持独占锁直到TRA1 transaction completes)。然后,THR2线程转到第1行并尝试查询此实体。不应该阻止THR2,因为TRA2事务尝试获取读锁定而其他事务TRA1持有该实体的独占写锁定吗?
如果我从第2点为READ UNCOMMITED隔离级别重现场景,则执行TRA2事务的THR2即使在refreshing之后也未查看THR1在TRA1事务中所做的更改或查询实体再次(&#34;评估表达式&#34;在调试下)。为什么呢?
答案 0 :(得分:1)
技术上可以通过设置读锁来实现读取提交。但不一定。如果您的DBMS支持MVCC,您总是读取已提交的数据(除了在您自己的事务中更改的内容),而不设置锁定。
所以我怀疑你使用oracle,mysql(INNODB)或postgres进行测试?所有这些DBMS都支持MVCC作为默认值,因此它们永远不会设置共享读锁。
因为您正在使用Oracle&#34; MVCC&#34;即使您在实体中配置了数据库,也不会实施2PL协议。如果您想了解在本机语句中DBMS上真正做了什么,只需像在persistence.xml中那样激活本机语句的输出:
<property name="hibernate.show_sql" value="true" />
也许您还应该看看transaction-isolation-levels-relation-with-locks-on-table 或首先在:locks and oracle