深度剖析 MySQL 事務隔離

2021-09-24 17:56:42 字數 2747 閱讀 3913

今天主要分享下mysql事務隔離級別的實現原理,因為只有innodb支援事務,所以這裡的事務隔離級別是指innodb下的事務隔離級別。

讀未提交:乙個事務可以讀取到另乙個事務未提交的修改。這會帶來髒讀,幻讀,不可重複讀問題

讀已提交:乙個事務只能讀取另乙個事務已經提交的修改。其避免了髒讀,仍然存在不可以重複讀和幻讀問題

可重複讀:同乙個事務中多次讀取相同的資料返回的結果是一樣的。其避免了髒讀和不可重複讀問題,但是幻讀依然存在

序列化:事務序列之行。避免了以上所有問題

以上是sql-92標準中定義的四種隔離級別。在mysql中,預設的隔離級別是repeatable-read(可重複讀),並且解決了幻讀問題。

注:不可重複讀重點在於update和delete,而幻讀的重點在於insert。

mvcc的全稱是多版本併發控制。mvcc使得innodb的事務隔離級別下執行一致性讀操作有了保證。

簡單說就是為了查詢一些正在被另乙個事務更新的行,並且可以看到它們被更新之前的值。這是乙個用來增強併發性的強大技術,可以使得查詢不用等待另乙個事務釋放鎖。

如下圖所示:

mvcc會給每一行增加三個字段,分別是:db-trx-id、db-roll-ptr、db-row-id

增刪查改

在innodb中,給每行增加兩個隱藏欄位來實現mvcc,乙個用來記錄資料行的建立時間,另乙個用來記錄行的過期時間。

在實際操作中,儲存的並不是時間,而是事務版本號,每開啟乙個新事務,事務的版本號就會遞增。所以增刪改查中對版本號的作用如下:

select:

讀取建立版本小於或等於當前事務版本號,並且刪除版本為空或大於當前事務版本的記錄。這樣可以保證在讀取之前記錄都是存在的

insert:

將當前事務的版本號儲存至行的建立版本號

update

新插入一行,並以當前事務版本號作為新行的建立版本號,同時將原記錄行的刪除版本號設定為當前事務版本號

delete

將當前事務版本號儲存至行的刪除版本號

快照讀和當前讀

普通的 select 就是快照讀,而 update,delete,insert,select...lock in share mode,select...for update 就是當前讀

首先看看下面的圖:

1、鎖定讀

在乙個事務中,標準的select語句是不會加鎖,但是有兩種情況例外。

select ... lock in share mode:給記錄假設共享鎖,這樣其他事務職能讀不能修改,直到當前事務提交

select ... for update:給索引記錄加鎖,這種情況跟update的加鎖情況是一樣的

2、一致性非鎖定讀

consistent read(一致性讀),innodb用多版本來提供查詢資料庫在某個時間點的快照。

如果隔離級別是repeatable read,那麼在同乙個事務中的所有一致性讀都讀的是事務中第乙個的讀讀到的快照;如果是read committed,那麼乙個事務中的每乙個一致性讀都會讀到它自己重新整理的快照版本。

consistent read(一致性讀)是read committed和repeatable read隔離級別下普通select語句預設的模式。一致性讀不會給它鎖訪問的表加任何形式的鎖,因此其他事務可以同時併發的修改它們

record locks(記錄鎖):在索引記錄上加鎖

gap locks(間隙鎖):在索引記錄之間加鎖,或者在第乙個索引記錄之前加鎖,或者在最後乙個索引記錄之後加鎖

next-key locks:在索引記錄上加鎖,並且在索引記錄之前的間隙加鎖。相當於record locks與gap locks的乙個結合

假如乙個索引包含以下幾個值:10,11,13,20.那麼這個索引的next-key鎖將會覆蓋以下區間:

(negative infinity, 10]

(10, 11]

(11, 13]

(13, 20]

(20, positive infinity)

在預設的隔離級別中,普通的select用的是一致性讀不加鎖。而對於鎖定讀,update和delete,則需要加鎖,至於加什麼鎖是有不同情況的。

如果對乙個唯一索引使用了唯一的檢索條件,那麼只需要鎖定相應的索引記錄就好;如果是沒有使用唯一索引作為檢索條件,或者用到了索引範圍掃瞄,那麼將會使用間隙鎖或者next-key鎖來以此阻塞其他會話向這個範圍內的間隙插入資料

利用mvcc實現一致性非鎖定讀,保證在同乙個事務中多次讀取相同的資料返回的結果是一樣的,解決了不可重複讀問題.

利用gap locks和next-key可以阻止其他事務在鎖定區間內插入資料,解決了幻讀問題.

總之,mysql的預設隔離級別的實現依賴於mvcc和鎖,準確點說就是一致性讀和鎖。

深度剖析 MySQL 事務隔離!

今天主要分享下mysql事務隔離級別的實現原理,因為只有innodb支援事務,所以這裡的事務隔離級別是指innodb下的事務隔離級別。1 讀未提交 乙個事務可以讀取到另乙個事務未提交的修改。這會帶來髒讀,幻讀,不可重複讀問題 2 讀已提交 乙個事務只能讀取另乙個事務已經提交的修改。其避免了髒讀,仍然...

mysql事物隔離 深度剖析 MySQL 事務隔離

概述 今天主要分享下mysql事務隔離級別的實現原理,因為只有innodb支援事務,所以這裡的事務隔離級別是指innodb下的事務隔離級別。隔離級別 讀未提交 乙個事務可以讀取到另乙個事務未提交的修改。這會帶來髒讀,幻讀,不可重複讀問題 讀已提交 乙個事務只能讀取另乙個事務已經提交的修改。其避免了髒...

mysql事務隔離最高 Mysql事務隔離級別

mysql官方文件顯示 innodb中每個隔離級別的詳細描述如下 read uncommitted select語句以非鎖定方式被執行,但是乙個可能更早期版本的記錄會被用到。因此,使用這個隔離級別,比如,讀是不連貫的。著也被稱為 髒讀 dirty read 另外,這個隔離級別象read commit...