MySQL [pom_5]> select @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+
若是事務隔離級別顯示REPEATABLE-READ,便是可重複讀。html
(引自: Innodb中的事務隔離級別和鎖的關係)sql
在數據庫操做中,爲了有效保證併發讀取數據的正確性,提出的事務隔離級別。咱們的數據庫鎖,也是爲了構建這些隔離級別存在的。數據庫
隔離級別 | 髒讀(Dirty Read) | 不可重複讀(NonRepeatable Read) | 幻讀(Phantom Read) |
---|---|---|---|
未提交讀(Read uncommitted) | 可能 | 可能 | 可能 |
已提交讀(Read committed) | 不可能 | 可能 | 可能 |
可重複讀(Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
未提交讀(Read Uncommitted):容許髒讀,也就是可能讀取到其餘會話中未提交事務修改的數據bash
提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重複讀)併發
可重複讀(Repeated Read):可重複讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重複讀,可是還存在幻象讀性能
串行讀(Serializable):徹底串行化的讀,每次讀都須要得到表級共享鎖,讀寫相互都會阻塞測試
在可重複讀中,該sql第一次讀取到數據後,就將這些數據加鎖(悲觀鎖),其它事務沒法修改這些數據,就能夠實現可重複讀了。但這種方法卻沒法鎖住insert的數據,因此當事務A先前讀取了數據,或者修改了所有數據,事務B仍是能夠insert數據提交,這時事務A就會發現莫名其妙多了一條以前沒有的數據,這就是幻讀,不能經過行鎖來避免。須要Serializable隔離級別 ,讀用讀鎖,寫用寫鎖,讀鎖和寫鎖互斥,這麼作能夠有效的避免幻讀、不可重複讀、髒讀等問題,但會極大的下降數據庫的併發能力。code
可是MySQL、ORACLE、PostgreSQL等成熟的數據庫,出於性能考慮,都是使用了以樂觀鎖爲理論基礎的MVCC(多版本併發控制)來實現。htm
對相同db實例建立兩個鏈接:a和b,來測試select, select for update, update語句的生效狀況事務
a先提交 | b先提交 | |
---|---|---|
a先開啓事務 | b的update內容 | a的update內容 |
a先開啓事務 | b的update內容 | a的update內容 |
結果是誰最後提交,誰的結果生效
a使用select for update | a使用select for update | a使用update | |
---|---|---|---|
a開啓事務,b不開啓 | b裏面的select for update和update被阻塞 | b不受影響 | b裏面的select for update和update被阻塞 |
a不開啓事務,b開啓 | b不受影響 | b不受影響 | b不受影響 |
a,b開啓事務 | b裏面的select for update和update被阻塞 | b不受影響 | b裏面的select for update和update被阻塞 |
a,b不開啓事務 | b不受影響 | b不受影響 | b不受影響 |
結果是隻有使用begin顯式開啓事務時,使用select for update纔會對數據加上行級鎖,對其餘鏈接的的select for update(對select沒有影響)和update形成阻塞效果。
下面是a開啓事務,而後使用a使用select for update,接着b使用select for update/select,a執行updat,最後commit,觀察整個過程當中b的查詢效果。
b使用select for update | b使用select | |
---|---|---|
b開啓事務 | b裏面的select for update被阻塞,a提交後,b讀到的是a修改的內容 | b不受a阻塞,讀到的還是b事務開啓時的內容 |
b不開啓事務 | b裏面的select for update被阻塞,a提交後,b讀到的是a修改的內容 | b不受a阻塞,讀到的數據在a提交後變化 |
a先執行select for update | a先執行update | |
---|---|---|
b後執行select | 未阻塞 | 未阻塞 |
b後執行select for update | 阻塞 | 阻塞 |
b後執行update | 阻塞 | 阻塞 |