如何在Hibernate中获取共享和独占锁

时间:2017-12-02 23:06:52

标签: java spring hibernate transactions isolation-level

我尝试理解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数据库。

请考虑以下情况:

  1. 让我们假设线程THR1步骤到第1行并查询对象。如果我理解正确,该线程创建的事务TRA1将获取查询的entiry的共享读锁。然后,如果THR2线程步骤到第3行尝试获取该实体的独占写锁定,那么THR2是否应该被阻塞,直到TRA1释放读锁定?

  2. 假设线程THR1步进第3行并获取实体的独占写锁(保持独占锁直到TRA1 transaction completes)。然后,THR2线程转到第1行并尝试查询此实体。不应该阻止THR2,因为TRA2事务尝试获取读锁定而其他事务TRA1持有该实体的独占写锁定吗?

  3. 如果我从第2点为READ UNCOMMITED隔离级别重现场景,则执行TRA2事务的THR2即使在refreshing之后也未查看THR1在TRA1事务中所做的更改或查询实体再次(&#34;评估表达式&#34;在调试下)。为什么呢?

1 个答案:

答案 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