MySQL InnoDB MVCC 能否完全解決幻讀?


幻讀是指多事務並發中一個事務讀到了另一個事務insert的記錄。

在REPEATABLE READ隔離級別下,假設事務T1執行后,事務T2開始執行,並新增一條記錄,然后事務T2提交,這時在事務T1中執行select是看不到事務T2新增的這條記錄的。因為在事務T1生成readview的時刻,事務T2屬於未來事務,所以是看不到事務T2新增的這條記錄的。

假設有如下場景:

# 表結構如下
CREATE TABLE hero (
    number INT,
    name VARCHAR(100),
    country varchar(100),
    PRIMARY KEY (number),
    KEY idx_name (name)
) Engine=InnoDB CHARSET=utf8;

# 事務T1,REPEATABLE READ隔離級別下
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM hero WHERE number = 30;
Empty set (0.01 sec)

# 此時事務T2執行了:INSERT INTO hero VALUES(30, 'g關羽', '魏'); 並提交

mysql> UPDATE hero SET country = '蜀' WHERE number = 30;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * FROM hero WHERE number = 30;
+--------+---------+---------+
| number | name    | country |
+--------+---------+---------+
|     30 | g關羽   | 蜀      |
+--------+---------+---------+
1 row in set (0.01 sec)

在REPEATABLE READ隔離級別下,T1第一次執行普通的SELECT語句時生成了一個ReadView,之后T2向hero表中新插入了一條記錄便提交了,ReadView並不能阻止T1執行UPDATE或者DELETE語句來對改動這個新插入的記錄(因為T2已經提交,改動該記錄並不會造成阻塞),但是這樣一來這條新記錄的trx_id隱藏列就變成了T1的事務id,之后T1中再使用普通的SELECT語句去查詢這條記錄時就可以看到這條記錄了,也就把這條記錄返回給客戶端了。因為這個特殊現象的存在,你也可以認為InnoDB中的MVCC並不能完完全全的禁止幻讀。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM