InnoDB一致性非鎖定讀(Consistent Nonlocking Reads)
阿新 • • 發佈:2019-02-01
一致性讀(consistend read)
一致性讀(consistend read)指的是InnoDB使用多版本查詢資料庫在某個時間點的快照。此查詢可以看到該時間點之前提交的事務所做的更改並且不會被之後的修改或者未提交事務所影響。但是對於同一事務中的較早語句的修改則不適用此規則,這種情況會產生以下異常:如果你更新表中的某些行,一次SELECT可能看到更新行的最新版本也可能看到任一行的舊版本;如果其它會話同時更新到同一個表,則可能會看到該表處於資料庫中從未存在過的狀態。
多版本併發控制
- 當事務隔離級別為REPEATABLE READ時,同一個事務中的一致性讀都是讀取的是該事務下第一次查詢所建立的快照。
- 當事務隔離級別為READ COMMITTED時,同一事務下的一致性讀都會建立和讀取此查詢自己的最新的快照
一致性讀是InnoDB在REPEATABLE READ和READ COMMITTED事務隔離中處理SELECT語句的預設模式。一致性讀不會在表上設定任何鎖,所以其它會話可以對錶進行讀寫操作。
資料庫狀態的快照適用於事務中的SELECT語句,而不一定適用於DML語句。如果執行INSERT或者UPDATE某些行然後提交該事務,則從另一個併發REPEATABLE READ事務發出的DELETE或UPDATE語句則會影響那些剛剛提交的資料行。下面這個示例展示了這種場景:
一致的讀取不適用於某些DDL語句
- 一致性讀不適用於DROP TABLE,因為表已經被InnoDB銷燬了
- 一致性讀不適用於ALTER TABLE,因為ALTER TABLE實際是生成一張原始表的臨時表,並在構建完成後刪除原始表。在事務中進行一致的讀取時,新表中的行不可見,這種情況下事務會返回 ER_TABLE_DEF_CHANGED錯誤(表定義已更改,請重試事務)
在沒有指定FOR UPDATE或者LOCK IN SHARE MODE的情況下INSERT INTO … SELECT,UPDATE …(SELECT)和CREATE TABLE …等語句中的的讀取會有以下差異:
- 預設情況下,就像READ COMMITTED一樣,即使在同一事務中,每個一致性讀都會建立和讀取自己的快照
- 如果將innodb_locks_unsafe_for_binlog設定為了enable並且事務隔離級別不是SERIALIZABLE,則讀操作不會再行上加鎖