深度剖析 MySQL 事務隔離!

2021-09-24 19:24:24 字數 3672 閱讀 3778

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

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

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

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

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

以上是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

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和鎖,準確點說就是一致性讀和鎖。

因為轉賬的交易場景 聯想到要加transaction事物 但是事物是什麼?

4個特性:原子性,一致性,隔離性,永續性

由於併發較大,session較多,事物存在幾個問題:

1、sessiona select sessionb update

但沒有commit session select 兩次查詢的資料不一樣

髒讀2、sessiona select sessionb update成功了 sessiona select 兩次讀取的資料不一樣,導致不可重複讀

不可重複讀

3、sessiona select sessionb insert 成功了 sessiona select 讀了兩條資料

幻讀 資料庫為了解決這三個問題,

sql92提出了事物的隔離級別 1、未提交讀:啥也不解決 2、已提交讀:不讀未提交的事物資料,解決了髒讀 3、可重複讀:解決不了幻讀 4、序列操作:缺點是效率太低,容易產生阻塞

上述隔離級別的實現方式是 1、snapshot 2、加上lock

lock又分行級鎖和表級鎖 以innodb為例:行級鎖,又分共享鎖和排他鎖 表級鎖:意向共享鎖和意向排它鎖,為了解決效率問題

鎖的原理:是鎖的索引

鎖演算法: 1、臨鍵鎖(next-key lock) innodb:預設採用的是next-key

lock演算法,因為innodb的設計預設是id為自增主鍵 2、間隙鎖(gap lock)

屬於寫鎖:鎖的是間隙中的insert、update操作,不鎖select,這樣innodb就解決了幻讀的問題 3、(記錄鎖)record

深度剖析 MySQL 事務隔離

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

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

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

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

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