透徹解讀mysql的可重複讀 幻讀及實現原理

2021-10-06 03:53:27 字數 2262 閱讀 6674

事務隔離級別有四種,mysql預設使用的是可重複讀,mysql是怎麼實現可重複讀的?為什麼會出現幻讀?是否解決了幻讀的問題?

read uncommitted(未提交讀)

在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。讀取未提交的資料,也被稱之為髒讀(dirty read)。該級別用的很少。

read committed(提交讀)

這是大多數資料庫系統的預設隔離級別(但不是mysql預設的)。它滿足了隔離的簡單定義:乙個事務只能看見已經提交事務所做的改變,換句話說就是事務提交之前對其餘事務不可見。這種隔離級別也支援不可重複讀(nonrepeatable read),因為同一事務的其他例項在該例項處理其間可能會有新的commit,所以同一select查詢可能返回不同結果。

repeatable read(可重複讀)

這是mysql的預設事務隔離級別,它確保同一事務的多個例項在併發讀取資料時,會看到同樣的資料行。不過理論上,這會導致另乙個棘手的問題:幻讀 (phantom read)。簡單的說,幻讀指當使用者讀取某一範圍的資料行時,另乙個事務又在該範圍內插入了新行,當使用者再讀取該範圍的資料行時,會發現有新的「幻影」 行。innodb和falcon儲存引擎通過多版本併發控制(mvcc,multiversion concurrency control)機制解決了該問題(mysql徹底解決了幻讀問題?請往下看)。

serializable(可序列化)

這是最高的隔離級別,它強制事務都是序列執行的,使之不可能相互衝突,從而解決幻讀問題。換言之,它是在每個讀的資料行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。

事務隔離級別

髒讀不可重複讀

幻讀讀未提交(read-uncommitted)是是

是不可重複讀(read-committed)否是

是可重複讀(repeatable-read)否否

是序列化(serializable)否否

否在mysql的眾多儲存引擎中,只有innodb支援事務,所有這裡說的事務隔離級別指的是innodb下的事務隔離級別。

mvcc多版本併發控制(multi-version concurrency control)是mysql中基於樂觀鎖理論實現隔離級別的方式,用於實現讀已提交和可重複讀取隔離級別。

在《高效能mysql》中對mvcc的解釋如下

新建一張表test_zq如下

idtest_id

db_trx_id

db_roll_pt

begin;-- 獲取到全域性事務id

insert into `test_zq` (`id`, `test_id`) values('5','68');

insert into `test_zq` (`id`, `test_id`) values('6','78');

commit;-- 提交事務

複製**

當執行完以上sql語句之後,**中的內容會變成:

idtest_id

db_trx_id

db_roll_pt568

1null678

1null

可以看到,插入的過程中會把全域性事務id記錄到列 db_trx_id 中去

對上述**做刪除邏輯,執行以下sql語句(假設獲取到的事務邏輯id為 3)

begin;--獲得全域性事務id = 3

delete test_zq where id = 6;

commit;

複製**

執行完上述sql之後資料並沒有被真正刪除,而是對刪除版本號做改變,如下所示:

idtest_id

db_trx_id

db_roll_pt568

1null678

13mvcc邏輯流程-修改

修改邏輯和刪除邏輯有點相似,修改資料的時候 會先複製一條當前記錄行資料,同事標記這條資料的資料行版本號為當前是事務版本號,最後把原來的資料行的刪除版本號標記為當前是事務。

執行以下sql語句:

begin;-- 獲取全域性系統事務id 假設為 10

update test_zq set test_id = 22 where id = 5;

commit;

複製**

執行後**實際資料應該是:

idtest_id

db_trx_id

db_roll_pt568

110678

13522

10null

mysql可重複讀和幻讀例項

mysql的預設事務級別是 可重複讀 其中可重複讀是通過mvcc來實現的又叫快照讀,在事務中的讀操作通過對當前的資料庫中記錄乙個版本,以後的讀操作只會讀取記錄的版本,因此相當於對資料庫的資料建立了乙個快照資料,因此叫做快照讀,其不用對資料庫中的資料進行加鎖又叫做樂觀鎖。同時rr事務級別的mysql通...

mysql 可重複讀。

一 可重複讀 我們先看看現象,再分析原理。我的mysql版本是5.5。下面是一張表,只有一條資料,並且我開啟了事物 此時,另乙個事物將record加1,因此我在開啟乙個命令列客戶端,執行下面的命令 成功加1之後,實際上,資料庫中record肯定是2。然後回到之前的客戶端,再查一次 沒毛病,recor...

mysql可重複讀

mysql innodb的預設隔離級別是可重複讀,之前理解有些偏差,查閱一些資料後總結出幾點 首先有兩個概念 一致性檢視 當乙個事務開啟時,innodb會生成乙個檢視,這個檢視是邏輯檢視,通過undo log和row tranzaction id控制實現。在該事務的任何時間點,一致性檢視中的資料都是...