MySQL中的鎖、隔離等級和讀場景

1、導言線程

關於MySQL中的鎖還有隔離等級這類話題,其概念性的解釋早已氾濫。記住其概念,算不上什麼。更重要的是思考:他們的區別和聯繫在哪兒,爲何會有這樣的概念。事務

1)MySQL的鎖(Lock)分爲行鎖(Row Lock)和表鎖(Table Lock),鎖自己又分爲讀鎖(Read Lock)和寫鎖(Write Lock)。it

2)隔離等級分爲Read uncommitted, Read committed, Repeatable reads, Serializableio

3)在常見的讀場景(Read phenomenon)中,會出現Dirty read, Non-repeatable reads以及Phantom Readstable

爲何要這麼分類,三個類別的概念是如何相互聯繫的。這裏談談個人思考。date

 

2、發現問題:Read phenomenonselect

所謂Dirty read,髒讀,以下例所示統計

select age from students where id = 9數據

                                                                     update table students set age = 12 where id = 9tab

select age from students where id = 9

                                                                    rollback

髒讀的關鍵在於,左側的事務A中的第二次讀操做讀到了事務B並無提交的數據,致使出錯。關鍵點在於事務B尚未提交。

-------------------------------------------------------------------------------------------------------------------------------

所謂Non-repeatable reads,不可重複讀,以下例所示

select age from students where id = 9

                                                                  update table students set age = 12 where id = 9

                                                                  commit

select age from students where id= 9

commit

不可重複讀的關鍵,在於左側的事務A中的第二次讀操做讀到了事務B中已經提交的數據,致使出錯。關鍵點在於事務B已經提交。

-----------------------------------------------------------------------------------------------------------------------------------

Phantom Read,幻讀,以下例所示

select * from students where id > 3 and id < 99 

                                                                          insert into students (id, name, age) values (12, "zs", 27)

                                                                          commit

select * from students where id > 3 and id < 99 

commit

幻讀的關鍵,在於在集合統計層面上,出現了不可重複讀,是一種特殊的不可重複讀。不可重複讀是修改數據,而幻讀是新增數據。

-----------------------------------------------------------------------------------------------------------------------------------

那爲何要分爲這三種層次的read phenomena?

這是由於,這三個層次實現了B事務的「縮小化」和「疊加」。從最開始B事務和A事務是交集狀態,到後來B事務位於A事務內部, 再到最後由單個記錄變爲多條記錄。本質上是這樣一種遞進關係。

 

2、分析問題:Isolation

爲了依次避免上述每個問題,就須要逐步採起更爲嚴格的措施。這也就出現了隔離狀態(Isolation)

1)啥都不避免,最爛的約束,就是Read uncommitted。這個uncommitted單詞是有意味的,說白了就是未提交,也就是髒讀中出現的狀況。

2)避免髒讀,就是Read committed。這個committed單詞也是有意思的,是已提交。如此也就排除了髒讀的狀況,可是仍會有不可重複讀和幻讀的狀況。

3)避免髒讀和不可重複讀,就是 Repeatable reads。對應的正好是non-repeatable。可是仍會有幻讀狀況。

4)避免全部狀況,那就是Serializable。

 

3、解決解決:Lock

這樣逐級進行分類,實際上也爲解決這些問題提供了一種策略,那就是「鎖」。

讀鎖(Read Lock)還有一個學名,叫作Shared Lock(共享鎖)。寫鎖(Read Lock)也叫做排它鎖(Exclusive Lock)

某線程一旦得到寫鎖,其餘的線程都將沒法得到任何鎖,不管寫鎖仍是讀鎖,都會被掛起,直到該寫鎖釋放。

某線程得到了讀鎖,其餘線程仍舊能夠得到讀鎖,但沒法獲取寫鎖。直到讀鎖釋放。

咱們來鎖看看是怎麼解決上述read phenomena的

1)Read uncommitted。這個就是啥鎖都不要。對吧。裸奔

2)Read committed。這個是要作到事務B可以完整提交,那好,就用一個寫鎖,保證事務B在執行過程當中始終擁有一個寫鎖。至於事務A中的讀,就不給鎖了,或者換一個說法,每次select的時候會得到一個讀鎖,select操做完成後當即釋放。總之讀鎖是不可能維持整個事務過程的。如此一來,避免了髒讀,卻沒法避免不可重複讀。

3)Repeatable reads。這下除了寫鎖,還得必須保證讀鎖了,也就是說,事務A必須擁有讀鎖,事務B必須有寫鎖,鎖的生存期爲整個事務過程。二者不可交叉。不可重複讀的問題也解決了。

4)Serializable。如何克服統計層面上的幻讀呢?如今咱們不只要保證單條數據記錄的可重複讀,還要保證多條記錄在統計意義上的可重複讀,那就是有采用表鎖了(Table Lock),固然也不必定要鎖全表,因此最爲準確的說法,是用範圍鎖(Range Lock),把多條記錄都上鎖。講到這裏,也就很清楚了,1-3是不需範圍鎖的。

 

4、結語

鎖,隔離等級,讀場景,就是這麼關聯到了一塊兒:發現問題,分析問題,解決問題。

相關文章
相關標籤/搜索