数据库 · 13 10 月, 2024

InnoDB,快照讀,在RR和RC下有何差異?(很多人,以為自己懂了…)

InnoDB,快照讀,在RR和RC下有何差異?(很多人,以為自己懂了…)

在資料庫管理系統中,InnoDB 是 MySQL 的一個重要存儲引擎,因其支持事務、行級鎖定和外鍵等特性而廣受歡迎。快照讀(Snapshot Read)是 InnoDB 中的一個重要概念,尤其在不同的隔離級別下,其行為會有所不同。本文將深入探討快照讀在可重複讀(Repeatable Read, RR)和讀取已提交(Read Committed, RC)隔離級別下的差異。

快照讀的基本概念

快照讀是指在查詢時,資料庫會返回某一時刻的數據快照,而不是當前的數據狀態。這意味著即使在查詢過程中,其他事務對數據進行了修改,快照讀仍然會返回查詢開始時的數據狀態。這一特性使得快照讀在高併發環境中能夠有效避免鎖競爭。

隔離級別概述

在 SQL 標準中,隔離級別定義了事務之間的可見性和相互影響程度。主要有四種隔離級別:

  • 讀取未提交(Read Uncommitted)
  • 讀取已提交(Read Committed)
  • 可重複讀(Repeatable Read)
  • 序列化(Serializable)

在這裡,我們將重點關注讀取已提交和可重複讀這兩個隔離級別。

快照讀在讀取已提交(RC)下的行為

在讀取已提交的隔離級別下,快照讀會返回已提交的數據。這意味著如果一個事務在查詢過程中對數據進行了修改,這些修改只有在事務提交後,才會對後續的快照讀可見。這樣的設計可以有效避免「髒讀」的問題。

-- 事務 A
START TRANSACTION;
UPDATE users SET balance = balance - 100 WHERE id = 1;
-- 事務 B
SELECT * FROM users WHERE id = 1; -- 這裡會看到事務 A 提交前的數據
COMMIT; -- 事務 A 提交
-- 事務 B 再次查詢
SELECT * FROM users WHERE id = 1; -- 現在會看到事務 A 提交後的數據

快照讀在可重複讀(RR)下的行為

在可重複讀的隔離級別下,快照讀的行為有所不同。當一個事務開始時,它會獲得一個快照,並在整個事務期間保持這個快照的可見性。這意味著即使其他事務對數據進行了修改,事務 A 仍然會看到它開始時的數據狀態,這樣可以避免「不可重複讀」的問題。

-- 事務 A
START TRANSACTION;
SELECT * FROM users WHERE id = 1; -- 事務 A 獲得快照
-- 事務 B
UPDATE users SET balance = balance + 100 WHERE id = 1; -- 事務 B 修改數據
COMMIT; -- 事務 B 提交
-- 事務 A 再次查詢
SELECT * FROM users WHERE id = 1; -- 仍然會看到事務 A 開始時的數據

總結

快照讀在不同的隔離級別下有著明顯的差異。在讀取已提交(RC)下,快照讀只會返回已提交的數據,避免了髒讀的問題;而在可重複讀(RR)下,快照讀則保持了事務開始時的數據狀態,避免了不可重複讀的問題。理解這些差異對於設計高效的資料庫應用至關重要。

如果您對於資料庫管理或其他技術問題有興趣,歡迎訪問我們的網站了解更多資訊,特別是我們的 香港VPS 服務,為您的業務提供穩定的支持。