如何理解mysql 的事務隔離級別 repeatable read

gongchengship發表於2024-07-04

在MySQL中,事務隔離級別定義了事務之間如何相互隔離,以及資料的一致性和併發性如何平衡。REPEATABLE READ(可重複讀)是MySQL中四種事務隔離級別之一,它在保證資料一致性的同時,允許較高的併發性。

MySQL的四種事務隔離級別

  1. READ UNCOMMITTED(未提交讀)
  2. READ COMMITTED(提交讀)
  3. REPEATABLE READ(可重複讀)
  4. SERIALIZABLE(可序列化)

這四種隔離級別從低到高分別提供了不同程度的資料一致性和併發控制。

REPEATABLE READ 的特性

REPEATABLE READ 隔離級別下,事務在執行 SELECT 語句時,會看到在該事務開始時存在的資料狀態。這意味著在同一個事務中多次讀取同一行資料,結果是相同的,即使其他事務已經對資料進行了修改並提交。這種行為防止了不可重複讀(non-repeatable read),即在同一事務中多次讀取同一行資料得到不同結果的問題。

為了更好地理解 REPEATABLE READ,需要理解以下幾個關鍵概念:

1. 多版本併發控制(MVCC)

MySQL的InnoDB儲存引擎透過使用MVCC實現 REPEATABLE READ。MVCC允許事務在讀取資料時,不需要加鎖,從而提高併發效能。每行資料有多個版本,事務讀取的資料版本是在事務開始時的資料快照(snapshot)。這種機制使得讀取操作不會阻塞寫入操作,反之亦然。

2. 快照讀(Snapshot Read)

REPEATABLE READ 隔離級別下,普通的 SELECT 語句是快照讀。快照讀從事務開始時的快照讀取資料,不會受到其他事務修改資料的影響。

3. 當前讀(Current Read)

SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE 語句是當前讀。當前讀讀取的是最新的資料,並且會鎖定讀取的資料行以防止其他事務修改。這種讀方式用於需要對資料進行後續修改的場景。

4. 幻讀(Phantom Read)

REPEATABLE READ 隔離級別還解決了幻讀問題。幻讀是指在同一事務中兩次執行相同的查詢,但結果集不一致的問題。例如,在第一次查詢時沒有新插入的行,但在第二次查詢時有其他事務插入了新行。InnoDB透過間隙鎖(Gap Lock)和Next-Key鎖機制解決了幻讀問題。

示例

假設有一個表 employees,結構如下:

CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    salary DECIMAL(10, 2)
);

事務A:

START TRANSACTION;
SELECT * FROM employees WHERE id = 1;
-- 返回結果:{ id: 1, name: 'John', salary: 5000.00 }

事務B:

START TRANSACTION;
UPDATE employees SET salary = 6000.00 WHERE id = 1;
COMMIT;

事務A:

SELECT * FROM employees WHERE id = 1;
-- 仍然返回結果:{ id: 1, name: 'John', salary: 5000.00 }
COMMIT;

在事務A中,即使事務B已經提交了更新,事務A在第二次讀取時依然看到的是事務開始時的資料快照。

也就是說REPEATABLE READ 隔離級別透過MVCC機制,確保在一個事務中多次讀取相同資料時結果一致,防止了不可重複讀和幻讀問題,同時在不鎖定資料的情況下允許較高的併發性。這種隔離級別是MySQL InnoDB儲存引擎的預設隔離級別,適用於大多數應用場景,在提供資料一致性的同時,具有較好的併發效能。

相關文章