上一篇博客《Spring Transaction属性之Propagation》讲解了Propagation相关的知识,这篇博客主要关注于Isolation这个属性。
一、Isolation基础
请先移步Wikipedia:isolation.
Isolation Level VS Phenomena
上图来自wikipeida。
因为我们在申明Isolation Level时,我们仅仅关心什么Phenomena不会出现。所以,在SQL标准中,仅仅规定了Isolation Level会保证哪种读现象不会出现,而不会规定某种读现象一定会出现。
例如,在Isolation设置为Repeatable Read时,不会出现Dirty Read。但是可能会出现Phantoms。如在Postgres中,Repeatable Read的效果就等同于Serializable,而在其他的数据库,如DB2中,Repeatable Read会出现Phantom Read。
二、Isolation例子
Isolation本身前面的wikipedia的链接已经讲的很清楚了,这里我们用Spring Transaction来重现一个Phantom Read的情况。大家感受一下就行了。
假设我们有一张表叫User,User的id是主键。UserService提供了如下两个方法:
@Transactional(isolation = Isolation.READ_COMMITTED)
public void insertData() {
jdbcTemplate.update("insert into User (id, username, age) values (123, 'xxx', 19)");
doSleep(20000);
}
@Transactional(isolation = Isolation.READ_COMMITTED)
public void readRange() {
System.out.println(jdbcTemplate.queryForList("select * from User where uses > 18").size());
doSleep(40000);
System.out.println(jdbcTemplate.queryForList("select * from User where uses > 18").size());
}
如果我们同时执行这两个方法:那么insertData中的SQL会在两次Query之间执行,于是readRange的两次结果就会相差一。如果将READ_COMMITTED改为了REPEATABLE_READ,则两次结果会相同。
问题:如果我们的两个方法的Transaction Isolation声明不同,我们应该“听”哪一个的呢?如上面的例子,我们把任意一个改成SERIALIZABLE后,会出现什么样的结果呢?
三、Isolation加强版
下面是何登成的博客,有些关于加锁与Isolation之间关系的分析,很值得一读:
四、Isolation的实现
常见的实现包括加锁和MVCC(Multi Version Consistency Control),更多的参考资料,移步:
http://coolshell.cn/articles/6790.html
http://en.wikipedia.org/wiki/Multiversion_concurrency_control