1. 程式人生 > 實用技巧 >MySQL與隔離級別

MySQL與隔離級別

圖畫得有點醜…

引言

對於資料庫的事務ACID特性我在之前的一篇文章中寫過: 連結,用一張圖表示可以如下所示。 圖中的兩個矩形表示為兩個事務。在一個事務中可以體現

  1. 原子性(右側中的select update select三個操作都成功或都不成功)
  2. 一致性: 如果有多個表的話,多表之間的約束,比如外來鍵關係要保證不被破壞
  3. 永續性: 永續性表示資料庫的修改都要落到磁碟上,往往在機房斷電,崩潰等重大不可中斷的問題發生時體現。
    除此之外,還有再不同事務間體現的"隔離性"。
    在這裡插入圖片描述

事務三大伴生問題

1. 髒讀

讀取到未提交的資料,該資料可能在對應事務中的之後操作還有進一輪的操作,所以是"髒"的,不是最終的,不是"乾淨的"。

假設藍色線是執行順序,髒資料的讀取情況可以如下表示。
在這裡插入圖片描述

2. 不可重複讀

不可重複讀是指在一個事務內,多次讀同一資料,但讀取到的資料不一致的情況。要注意,不可重複讀要在"一個事務"中討論。
在這裡插入圖片描述

3. 幻讀

舉個例子: A事務修改表table中的所有資料,在A事務處理時B事務往表table中插入一條資料,從A的角度看,自己明明把所有資料都修改過了,怎麼還多出來一條資料? 感覺出現了幻覺似的。

MYSQL 隔離級別

mysql共有四種隔離級別,分別如下所列:
在這裡插入圖片描述
對於大多資料庫來說,已提交讀(read committed)是預設的隔離級別,但對於mysql來說,可重複讀(repeateable read)是預設的隔離級別

。以下關於mysql的隔離級別逐個進行表述:

1. 未提交讀(read uncommitted)

未提交讀是最低階的隔離級別,一般來說都不會選擇這個級別。缺點不少,優點不多。正如圖所示,髒讀、可不重複讀、幻讀都它中了招。

2. 已提交讀(read committed)

保證了讀到的任何資料都是提交的資料,避免讀到中間的未提交的資料

一個事務在未提交之前對於其他事務是不可見的。它不可見其他事務,其他事務不可見它。
從讀寫鎖的角度看: 本級別對選定物件的寫鎖(獨佔鎖)會一直保持到事務結束,但是讀鎖(共享鎖)在SELECT操作完成後會馬上釋放。

  1. 不可重複讀: 兩個讀操作間是會經歷"解讀鎖->上讀鎖"的過程,在"解->上"之間可能出現其他事務修改該資料的情況,造成在一個事務中兩次讀資料不一致的情況。
  2. 會有幻讀可能: 除了序列化,一般來說都有可能幻讀

3. 可重複讀(repeatable read)

這是mysql預設的隔離級別。

  1. 會有幻讀可能: 除了序列化,一般來說都有可能幻讀。mysql通過"索引間隙加鎖"的方式避免出現幻讀。

4. 序列化(seraible)

最高階的隔離級別,事務都排成一隊一個個執行,不會出現問題但加鎖解鎖的效能開銷很高,一般來說不用使用這個等級的隔離級別。

MVCC淺談

1. 介紹

MVCC不是mysql獨有的技術,在其他主流資料庫中也有MVCC技術的相關實現。MVCC技術可以用來減少讀鎖的新增,對於大多數的"讀多寫少"型資料庫,可以極大的提高資料庫效能。

MVCC可以初略劃分為樂觀鎖和悲觀鎖的類別。

在這裡插入圖片描述
正如圖所示,MVCC主觀上可以用 "每個表增加兩個欄位來進行錶行版本控制"來理解。

2. 隔離級別和相容性

MVCC只相容"已提交讀"、"可重複讀"兩個隔離級別。對於未提交讀和序列化的隔離級別不相容

3. 版本號(時間)賦值

在這裡插入圖片描述

參考文件

  1. https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB(%E5%9B%BE%E6%96%87%E8%AF%A6%E8%A7%A3).md
  2. https://blog.csdn.net/qq_28052907/article/details/75579201
  3. <<高效能MYSQL>>