這篇文章涉及到數據庫鎖的概念,個人一篇關於數據庫鎖的博客:http://www.javashuo.com/article/p-ywdxblsb-ms.html.html
這裏的討論是以innodb引擎做爲基礎,一個事務在執行前會去獲取本身須要的全部鎖,事務提交或者回滾後釋放鎖.mysql
事務隔離級別有如下五種:sql
1. TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示一個事務能夠讀取另外一個事務修改但尚未提交的數據。該級別不能防止髒讀,不可重複讀和幻讀,所以不多使用該隔離級別。好比PostgreSQL實際上並無此級別。數據庫
這個是最低的一種隔離級別,沒有任何防範措施.安全
2. TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示一個事務只能讀取另外一個事務已經提交的數據。該級別能夠防止髒讀,這也是大多數狀況下的推薦值。併發
髒讀產生的緣由是一個事務A對一行數據進行了修改,隨後回滾了.另外一個事務B在事務A回滾以前讀到了被修改的那一行數據,這樣在事務A回滾以後,事務B的數據就是髒數據.該隔離級別下修改數據行時會加上寫鎖(排它鎖),當事務讀取被加鎖的數據行時,會從undo log中獲取最近的數據,這樣事務B就不能讀取到事務A未提交的數據,從而防止了髒讀,可是會產生不可重複讀和幻讀.oracle
3. TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示一個事務在整個過程當中能夠屢次重複執行某個查詢,而且每次返回的記錄都相同。該級別能夠防止髒讀和不可重複讀。性能
不可重複讀產生的緣由是事務A在第一次讀取一行數據以後,另外一個事務B對該行數據進行了修改而且提交,而後事務A再一次讀取該行數據,會發現兩次讀取數據不一致.在該隔離級別下,事務讀取數據時會加上讀鎖(共享鎖),共享鎖與排它鎖不能共存,因此這樣就可以保證本身在讀取事務時,數據不會被其餘事務修改,從而防止了不可重複讀,可是會產生幻讀.spa
4. TransactionDefinition.ISOLATION_SERIALIZABLE:全部的事務依次逐個執行,這樣事務之間就徹底不可能產生干擾,也就是說,該級別能夠防止髒讀、不可重複讀以及幻讀。可是這將嚴重影響程序的性能。一般狀況下也不會用到該級別。code
幻讀產生的緣由是事務A在對多行數據進行操做,例如將全部知足條件A的數據所有修改成X這樣的批量操做時,事務B插入了一條知足條件A的可是數據值不爲X的值,這樣事務A再次查詢時,就會發現有一行沒有被修,產生了執行失敗的幻覺.以上說的隔離級別都是對要操做的數據行進行加鎖實現的,而幻讀是進行insert操做產生的,insert是插入了一條新數據行,鎖是沒法影響到insert操做的,因此該隔離級別經過讓事務串行執行,從而達到防止幻讀的功能.
以上都是基於悲觀鎖,有他的實現原理就可以看出來,他們的併發性不是很好,因此大多成熟的數據庫,例如mysql,oracle等都會採用一種基於樂觀鎖的併發控制-----MVCC(多版本併發控制).
MVCC具體原理之後理解深入了在寫,這裏先說一下我如今對MVCC的理解:咱們不考慮隔離級別,單純的考慮MVCC的話,他不能防止髒讀,不可重複讀,幻讀,他的做用是爲了提升事務的併發度,由上面的各個隔離級別能夠看出,隔離級別越高,併發度越低,MVCC就是在下降隔離級別的同時提升安全性.舉一個例子:咱們使用REPEATABLE_READ隔離級別時會出現幻讀,可是咱們的系統要杜絕幻讀,但是咱們不想使用SERIALIZABLE隔離級別,由於併發度過低了,這個時候MVCC的做用就體現出來了,雖然他不能杜絕幻讀,可是若是使用了MVCC的話,那麼在REPEATABLE_READ隔離級別加上MVCC機制下,可能出現幻讀的狀況我只能想到一種:
當前系統版本號0,數據版本號0->事務A開啓版本號1,系統版本號1->事務B開啓版本號2,系統版本號2->事務B執行update->事務A執行insert,數據版本號2->事務B執行select,查詢版本號<=2,幻讀發生
若是想要徹底杜絕幻讀,那麼咱們能夠給程序增長保險機制,例如:裏面使用一個循環操做,每次update以後再查詢數據庫是否還有爲更改的數據,這樣的操做確定會很費時間.可是咱們使用了MVCC以後,發生幻讀的機率降低,那麼進入保險機制的機率就被減少,因此提升了併發度,同時解決了幻讀問題.