【问题标题】:Transaction isolation level REPEATABLE_READ using hibernate and jdbc使用hibernate和jdbc的事务隔离级别REPEATABLE_READ
【发布时间】:2013-02-23 02:31:25
【问题描述】:

我正在尝试开发一个演示来巩固我对 REPEATABLE_READ 隔离级别的理解。我尝试过使用 hibernate 和 jdbc 的演示。 JDBC 按预期工作,但 hibernate 不能。

我的期望是,如果我在一个会话中读取数据库行,并且我尝试从另一个会话中写入同一行,它应该阻塞直到第一个会话完成。

休眠:- 当我在线程 0 中“获取”一个对象(行)并休眠时,在线程 1 中我们尝试更新同一个对象(行),线程 1 应该等到线程0 次提交。

class HibernateExample7_IsolationRR_Read_Write_Thread implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(HibernateExample7_IsolationRR_Read_Write_Thread.class);

    SessionFactory sessionFactory;
    int sleep;
    int newnumberplate;
    public HibernateExample7_IsolationRR_Read_Write_Thread(SessionFactory sessionFactory, int sleep, int newnumberplate) {
        this.sessionFactory = sessionFactory;
        this.sleep = sleep;
        this.newnumberplate = newnumberplate;
    }

    public void run() {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        logger.info("TRYING TO GET VEHICLE 1");
        Vehicle vid1 = (Vehicle) session.get(Vehicle.class, Integer.valueOf(1));
        logger.info("GOT VEHICLE 1");
        vid1.setNumberplate(this.newnumberplate);
        logger.info("SET NUMBERPLATE FOR 1");
        try {
            Thread.sleep(sleep);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tx.commit();
        session.close();
        logger.info("COMMITED");
    }
}

hibernate.connection.url 是 jdbc:derby:isolation;create=true 并且 hibernate.connection.isolation 是 2。我制作了两个 HibernateExample7_IsolationRR_Thread 对象,并创建了一个场景,其中线程 0 获取车辆并长时间休眠。同时线程 1 尝试获取和更新 Vehicle。它甚至在线程 0 提交之前就成功提交。

由于 REPEATABLE_READ 隔离级别,T1 不应该等待提交。如果不是,那么它是 READ_COMMITED 隔离级别而不是 REPEATABLE_READ 隔离级别。

【问题讨论】:

  • 如果你使用的是 hsqldb 是什么版本?

标签: hibernate jdbc transactions


【解决方案1】:

你的期望是错误的。可重复读取并不意味着一个事务应该阻塞,而另一个事务读取同一行。这意味着在同一个事务中读取同一行两次应该返回相同的数据,即使另一个事务在第一次和第二次读取之间对该行提交了更改。

使用 Hibernate,您(或多或少)免费获得,因为第二次读取将返回一级缓存中的数据,而根本不需要访问数据库。

http://en.wikipedia.org/wiki/Isolation_%28database_systems%29#Non-repeatable_reads

另外,您正在使用不支持此隔离级别的数据库进行测试:

http://www.hsqldb.org/doc/2.0/guide/dbproperties-chapt.html#N15385

【讨论】:

  • 吹毛求疵:他会达到二级缓存,对吧?每个线程都有自己的会话。
  • @sharakan:不。一个线程,在同一个事务中两次获取同一个实体,第一次会访问数据库,第二次会访问一级缓存。因此它将具有可重复的读取,因为一级缓存将返回与第一次返回相同的数据(当然,除非在读取之间对实体进行了一些更改)。
  • 同意,但是他有两个单独的线程,每个线程都调用.openSession,因此有单独的一级缓存。
  • 这正是我的观点。每个线程都有自己的一级缓存,因此不受其他线程所做的事情的影响,这将导致单个线程内的可重复读取,这要归功于一级缓存不与其他线程共享。
  • 啊,我明白你的意思了。当你这么说的时候,我想:“……因为第二次读取会从一级缓存返回数据,根本不用去数据库。”您指的是从他的示例中的第二个线程中读取的内容。我的错。
猜你喜欢
  • 2011-03-19
  • 2014-08-28
  • 1970-01-01
  • 2021-11-29
  • 2011-09-30
  • 2011-02-24
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
相关资源
最近更新 更多