上一篇博客《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