簡單的理解MySql 的事務隔離級別

回顧了一下數據庫事務相關的特性:ACID

原子性:指事務是數據操作的最小單位,要麼全部執行,要麼全部都不執行。

一致性:指事務執行前後,數據保持一致。比如銀行轉賬,A有1000塊,B有500塊,A轉給B 500塊,事務執行完後,數據也就是金額的總數並沒有改變,加起來還是1500,只不過是A少了500,B多了500。

隔離性: 當多個線程都開啓事務操作數據庫中的數據時,數據庫系統要能進行隔離操作,以保證各個線程獲取數據的準確性。

持久性:指事務對數據庫的操作是持久的,比如修改是永久生效的。

事務的隔離性是指在併發環境中,併發的事務是相互隔離的。SQL標準中定義了四種數據庫事務隔離級別,級別從低到高分別爲:讀未提交(Read Uncommitted)、讀已提交(Read Committed)、可重複讀(Repeatable Read)、串行化(Serializable)。在事務的併發操作中會出現髒讀、不可重複讀、幻讀。在事務的併發操作中第二類更新丟失可以通過樂觀鎖和悲觀鎖解決。

四種隔離級別:

   set tx_isolation='READ-UNCOMMITTED';


    1.未提交讀(隔離級別最低) : 會導致髒讀(未提交讀,事務T1在讀取數據時,沒有對數據加任何鎖,所以另外一個事務T2也可以讀取並隨意修改,然後T1提交事務讀出來的數據是被T2修改過的)

set tx_isolation='READ-COMMITTED';


    2.已提交讀 :解決了髒讀,會導致不可重複讀(已提交讀,事務T1在讀取數據時會對數據加行共享鎖,事務T2此時也可以讀取此行數據,但是不能給這行數據加入排他鎖,事務T1在結束讀取時釋放了行共享鎖,此時T2可以加排他鎖,而T1不能對數據進行讀取修改,直到T2結束,如果T2進行了某種修改,就會導致第二次T1再查詢時,兩次查詢到的結果不同,這樣雖然解決了髒讀,但是會產生不可重複讀)

set tx_isolation='REPEATABLE-READ';


    3.可重複讀 (mysql數據庫默認的隔離級別):  解決了不可重複讀,會導致幻讀(可重複讀,事務T1在讀取數據時會對數據加一個共享鎖,直到事務結束提交後纔會釋放共享鎖,這樣T2在T1執行過程中不能給數據加入排他鎖進行修改,從而避免了不可重複讀,但是會導致幻讀,因爲可重複讀隔離級別加的是行共享鎖,比如查詢10行數據,會給那10行數據都加入共享鎖,但是表是 沒有加鎖的,事務T2此時雖然不能修改那10行數據,但是可以往10行數據所在的表裏插入新的符合T1查詢條件的數據,這樣T1再次執行查詢時會發現多了幾條數據,就是幻讀。

set tx_isolation='SERIALIZABLE';


    4.串行化(隔離級別最高):   解決了髒讀,不可重複度,幻讀,但是會降低併發能力(序列化,事務T1在執行讀時會對數據所在的表添加表共享鎖,直到事務結束,在T1事務期間,T2只能讀取 這張表,但是不能進行其他的任何操作,寫操作也是一樣的,T1往表裏寫數據時同樣會對數據所在的表加上一個表排他鎖直到事務結束)。串行化加的不是表鎖,還是行級鎖,

它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。通俗地講就是,假如兩個事務都操作到同一數據行,那麼這個數據行就會被鎖定,只允許先讀取/操作到數據行的事務優先操作,只有當事務提交了,數據行纔會解鎖,後一個事務才能成功操作這個數據行,否則只能一直等待

Ps:共享鎖 Share Locks(S鎖)可以理解爲讀鎖,排他鎖 Exclusive Locks(X鎖)可以理解爲寫鎖。第一個事務給數據加了共享鎖,第二個事務也能給這些數據加共享鎖來讀取數據,但是不能給他加排他鎖來進行寫操作,除非第一個事務釋放了共享鎖,此時第二個事務才能加排他鎖來進行寫操作,S鎖和X鎖都屬於悲觀鎖。

樂觀鎖

    在更新語句中增加過濾條件,進行版本的判斷,可以是這條記錄的版本號、更新時間等。然後通過影響行數來判斷是否更新成功。

 悲觀鎖

共享鎖又稱爲讀鎖,簡稱S鎖,顧名思義,共享鎖就是多個事務對於同一數據可以共享一把鎖,共享鎖是用來讀取數據的。另外,一個事務獲取了同一數據的共享鎖,其他事務就不能獲取該數據的排它鎖。

    排它鎖又稱爲寫鎖,簡稱X鎖,顧名思義,排它鎖就是不能與其他所並存,如一個事務獲取了一個數據行的排它鎖,其他事務就不能再獲取該行的其它鎖,包括共享鎖和排它鎖。另外不存什麼事務隔離級別,update/insert/delete會自動獲取排它

  共享鎖獲取方式:select * from account where name='jack' lock in share mode;

  排它鎖獲取方式:select * from account where name='jack' for update;

 MySQL分爲表級鎖和行級鎖,共享鎖和排它鎖是行級鎖。

 通常,對於絕大多數的應用程序來說,可以優先考慮將數據庫系統的隔離級別設置爲讀已提交(Read Committed),這能夠在避免髒讀的同時保證較好的併發性能。儘管這種事務隔離級別會導致不可重複讀、幻讀和第二類丟失更新等併發問題,但較爲科學的做法是在可能出現這類問題的個別場合中,由應用程序主動採用悲觀鎖或樂觀鎖來進行事務控制。

參考文章:事務隔離級別,髒讀、不可重複讀、幻讀,樂觀鎖、悲觀鎖 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章