1. 程式人生 > >MySQL事務隔離級別以及實現原理

MySQL事務隔離級別以及實現原理

一、事務完整性問題

髒讀:可以讀取其他事務未提交的資料,如果該事務回滾,則資料為錯誤資料。

不可重複讀:A事務檢視,B事務修改提交,A事務再次檢視,資料不一樣。

幻讀:幻讀與不可重複讀相似,但不可重複讀重點在於update和delete,幻讀重點在於insert

t Session A                   Session B
|
| START TRANSACTION;          START TRANSACTION;
|
| SELECT * FROM t_bitfly;
| empty set
|                             INSERT INTO t_bitfly
|                             VALUES (1, 'a');
|
| SELECT * FROM t_bitfly;
| empty set
|                             COMMIT;
|
| SELECT * FROM t_bitfly;
| empty set
|
| INSERT INTO t_bitfly VALUES (1, 'a');
| ERROR 1062 (23000):
| Duplicate entry '1' for key 1
v (???剛剛明明告訴我沒有這條記錄的)

t Session A                  Session B
|
| START TRANSACTION;         START TRANSACTION;
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id   | value |
| +------+-------+
| |    1 | a     |
| +------+-------+
|                            INSERT INTO t_bitfly
|                            VALUES (2, 'b');
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id   | value |
| +------+-------+
| |    1 | a     |
| +------+-------+
|                            COMMIT;
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id   | value |
| +------+-------+
| |    1 | a     |
| +------+-------+
|
| UPDATE t_bitfly SET value='z';
| Rows matched: 2  Changed: 2  Warnings: 0
| (怎麼多出來一行)
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id   | value |
| +------+-------+
| |    1 | z     |
| |    2 | z     |
| +------+-------+
|

二、事務隔離級別


    1. 讀未提交(Read Uncommitted)

    原理:任何操作都不加鎖

    2. 讀提交(Read Commit)

原理:讀操作不加鎖,寫操作加鎖。讀被加鎖的資料時,讀事務每次都讀undo log中的最近版本,因此可能對同一資料讀到不同的版本(不可重複讀),但能保證每次都讀到最新的資料。

    3. 可重複讀(Reapable Read)

    原理:第一次讀資料的時候就將資料加行鎖(共享鎖),使其他事務不能修改當前資料,即可實現可重複讀。但是不能鎖住insert進來的新的資料,當前事務讀取或者修改的同時,另一個事務還是可以insert提交,造成幻讀。

    4. 序列化(Serializable)

    原理:鎖表,讀鎖和寫鎖阻塞。

三、InnoDB事務相關概念

●  redo log

    MySQL在開啟事務時,會將執行的SQL儲存到指定的log檔案,即redo log。當MySQL執行recovery時執行redo log裡的SQL操作即可。redo log不會被立即寫入磁碟,會先寫入redo buffer;當客戶端執行commit時,redo buffer的內容會視情況存入磁碟。

●  undo log

    與redo log相反,undo log是為了回滾事務而寫的日誌,具體內容就是copy事務開始前的資料(行)到undo buffer。

    與redo buffer一樣,undo buffer也是環形緩衝,當緩衝滿的時候buffer內容會被重新整理到磁碟。

    與redo log不同的是,undo log沒有獨立的磁碟檔案,所有的undo log均被存在主ibd資料檔案中(表空間)。