mysql四個隔離級別的介紹

mysql四個隔離級別的介紹

爲了解決“隔離”與“併發”的矛盾,ISO/ANSI SQL92定義了4個事務隔離級別,每個級別的隔離程度不同,允許出現的副作用也不同,應用可以根據自己的業務邏輯要求,通過選擇不同的隔離級別來平衡 “隔離”與“併發”的矛盾。

隔離級別(由高到低)
Serializable>Repeatable read>Read committed>Read uncommitted

四個隔離接的詳細介紹

  1. Read uncommitted(讀未提交)
    從字面意思來理解就是能讀取到未提交的數據,不過當然是另一線程的未提交數據,這樣到導致所謂的髒讀問題。
    髒讀:大抵便是兩個線程同時運行,第一個線程在操作數據,另一個線程也修改了相關的數據,都沒有進行提交,第一個線程就已經讀取到了。數據便讀到了線程2的相關修改,破壞了事務的隔離性。
    下面這段是所謂的專業術語寫的。
    一個事務正在對一條記錄做修改,在這個事務完成並提交前,這條記錄的數據就處於不一致狀態;這時,另一個事務也來讀取同一條記錄,如果不加控制,第二個事務讀取了這些“髒”數據,並據此做進一步的處理,就會產生未提交的數據依賴關係。這種現象被形象地叫做**“髒讀”**。

  2. Read committed(讀取已提交)
    從字面意思來理解就是能讀取到已經提交的數據,不過當然是另一線程的提交數據。第一個線程中可以讀取到第二個線程中已經提交的數據。不過還是會有所謂的缺點,那就是**“不可重複讀”
    "不可重複讀":大抵便是第一個線程中一個事務在讀取某些數據後,隔段時間再次用同樣的條件查詢數據,卻發現其讀出的數據已經發生了改變,出現了第一次事務中未有的數據。這種現象就叫做“不可重複讀”。即一個事務中兩次讀取數據,會出現數據不一致的問題。
    下面這段是所謂的專業術語寫的。
    一個事務在讀取某些數據後的某個時間,再次讀取以前讀過的數據,卻發現其讀出的數據已經發生了改變、或某些記錄已經被刪除了!這種現象就叫做
    “不可重複讀”**。

  3. Repeatable read(可重複讀取)
    從字面意思來理解就是一個事務中,多次讀取,查詢的數據是一致的。innodb已經通過mvcc,來保證這個特性。保證當前讀的情況下,當前事務只能看到,事務之前和自己的修改,別的均不可見,"不可重複讀"和"幻讀"都已經解決。不過依舊有缺點,那就是不能讀取到併發情況下,其他線程事務提交的最新數據。

  4. Serializable(可序列化)
    最安全級別,默認讀的時候,也加上共享讀鎖,阻止其他事物,修改相關數據。不過,性能麼,就差太多太多了!!

隔離級別雜談

在上面講到的併發事務處理帶來的問題中,
“髒讀”、“不可重複讀”和“幻讀”,其實都是數據庫讀一致性問題,必須由數據庫提供一定的事務隔離機制來解決。數據庫實現事務隔離的方式,基本上可分爲以下兩種。

  • 一種是在讀取數據前,對其加鎖,阻止其他事務對數據進行修改。
  • 另一種是不用加任何鎖,通過一定機制生成一個數據請求時間點的一致性數據快照(Snapshot),並用這個快照來提供一定級別(語句級或事務級)的一致性讀取。從用戶的角度來看,好像是數據庫可以提供同一數據的多個版本,因此,這種技術叫做數據多版本併發控制(MultiVersion Concurrency Control,簡稱MVCC或MCC),也經常稱爲多版本數據庫。

mvcc帶來的當前讀和快照讀

  • 快照讀
    相當於讀取的是查詢數據的最新快照版本,而並非最新的實時數據。
    不顯式加鎖的普通查詢,都是快照讀。諸如 select xx from table where field = value
  • 當前讀
    始終讀取最新數據,相當於Serializable級別的讀操作。
    顯式加鎖的查詢就是當前讀。如 select xx from table where field = value lock in share mode(加共享讀鎖),select xx from table where field = value for update (加排它鎖)

共享鎖和排它鎖的介紹共享鎖的排它鎖

代碼操作

數據庫版本信息,我的mysql版本8.0.19,innodb引擎。5.6前後,好像還是有點差距的,在此先說下。

命令相關

# 查看mysql版本
select version(); 
# 查看隔離級別
select @@transaction_isolation; 
# 設置隔離級別(其他幾個前面有)
set session transaction isolation level  serializable; 
# 顯式加共享鎖
select xx from table where field = value lock in share mode;
# 顯式加排它鎖
select xx from table where field = value for update;

驗證當前讀和快照讀

在這裏插入圖片描述
在這裏插入圖片描述
從操作中,我們已經得知,快照讀的缺點。不能獲取到實時數據,不過,快照讀,它不加鎖,性能好啊。

驗證共享鎖和排它鎖

在這裏插入圖片描述
在這裏插入圖片描述

驗證不可重複讀

自己動手試試吧。
先改下默認的隔離級別,然後在一個事務中查詢,另一個事務中修改,未提交讀,讀取已提交,還有可序列化,自己模擬一下場景,試試你就明白上面說的什麼意思了~~
自己動手,豐衣足食。

結語

數據庫的事務隔離越嚴格,併發副作用越小,但付出的代價也就越大,因爲事務隔離實質上就是使事務在一定程度上 “串行化”進行,這顯然與“併發”是矛盾的。同時,不同的應用對讀一致性和事務隔離程度的要求也是不同的,比如許多應用對“不可重複讀”和“幻讀”並不敏感,可能更關心數據併發訪問的能力。
大家只需要知道,魚與熊掌不可兼得,既想馬兒吃得少,又想馬兒跑的快,是不可能的。性能和數據一致性,你只能選擇一個,選擇最適合你的業務的隔離級別就好了,當然默認RR,已經能滿足大部分需求了~

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