关于Spring声明式事务的隔离级别。
最近在研究Spring事务的隔离级别Serializable,可是在一些实验中遇到了一些问题,实验过程如下:
有表 T ,它只有二个字段:id,name,这个表只一条数据,id=1;name='hello'
1、先在Oracle数据库验证Serializable这个隔离级别的情况。
事务A有如下过程:开启事务,设置事务级别为Serializable,睡眠30秒,从表T查询id=1的name值并打印到DBMS,提交事务。
事务B有如下过程:开启事务,设置事务级别为Serializable,更新id=1的name值为'world',提交事务。
现在先执行事务A,并且10秒内执行事务B,plsql上的确显示事务B是比事务A先结束的,此时DBMS的output上显示name值为hello,这个结果符合了事务在Serializable隔离级别时,事务是串先执行的。
2、在Spring中验证事务隔离级别为Serializable的情况,仍然用初始化的数据表T
有两个java方法:getName()、updateName(),
getName()方法有如下过程:睡眠30秒,从表T查询id=1的name值并打印到控制台。
updateName()方法有如下过程:更新id=1的name值为'world'。
Spring为这两个方法都配置了事务,传播性都为REQUIRED,隔离级别都为SERIALIZABLE。
现在main方法中通过多线程调用getName()和updateName()这两个方法,保证这样一个执行顺序:
getName()先执行,然后在10~20秒内执行updateName()方法,updateName()方法比getName()方法要先执行完。
这个执行后,通过在控制台的Spring Debug信息中可以看到执行过程如下:
a、为getName方法开启一个事务A,更改其隔离级别为SERIALIZABLE,程序睡眠30秒。
b、为updateName方法开启一个事务B,更改其隔离级别为SERIALIZABLE,更新name值为'world',提交事务B
c、getName程序睡眠结束,事务A继续执行,查找name字段的值,这时候居然输出为'world',提交事务A。
现在的问题是:Spring配置两个事务隔离级别都为SERALIZABLE的时候,居然会出现c这种情况。
明明是事务A先开启,那么按照串行事务的说法,不是说哪个事务先开启,就先执行完那个事务再执行后面的事务吗?
那么为什么c步打印到的name值不是hello值而是world值呢?
文字表达了这么多,也不知道大神们有没有耐心看下去了。。。