事務隔離級別:可重複讀

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語句的生效狀況事務

不使用select for update行級鎖

a先提交 b先提交
a先開啓事務 b的update內容 a的update內容
a先開啓事務 b的update內容 a的update內容

結果是誰最後提交,誰的結果生效

a先使用select for update, 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上鎖後修改提交,b讀取到的內容

下面是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使用begin開啓事務以後,select for update和update對鏈接b的阻塞效果

a先執行select for update a先執行update
b後執行select 未阻塞 未阻塞
b後執行select for update 阻塞 阻塞
b後執行update 阻塞 阻塞
相關文章
相關標籤/搜索