我正在尝试开发一个演示来巩固我对REPEATABLE_READ隔离级别的理解。我已经尝试使用hibernate和jdbc进行演示。 JDBC按预期工作,但是hibernate没有。
我的期望是,如果我在一个会话中读取数据库行,并且我尝试从另一个会话中写入相同的行,它应该阻塞直到第一个会话结束。
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。它甚至在Thread 0提交之前就成功提交了。
由于REPEATABLE_READ隔离级别,T1不应等待提交。如果没有,则它是READ_COMMITED隔离级别而不是REPEATABLE_READ隔离级别。
答案 0 :(得分: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