InnoDB一致性非鎖定讀(Consistent Nonlocking Reads)

一致性讀(consistend read)

一致性讀(consistend read)指的是InnoDB使用多版本查詢數據庫在某個時間點的快照。此查詢可以看到該時間點之前提交的事務所做的更改并且不會被之后的修改或者未提交事務所影響。但是對于同一事務中的較早語句的修改則不適用此規(guī)則,這種情況會產生以下異常:如果你更新表中的某些行,一次SELECT可能看到更新行的最新版本也可能看到任一行的舊版本;如果其它會話同時更新到同一個表,則可能會看到該表處于數據庫中從未存在過的狀態(tài)。

多版本并發(fā)控制

  • 當事務隔離級別為REPEATABLE READ時,同一個事務中的一致性讀都是讀取的是該事務下第一次查詢所建立的快照。

我們可以通過

  • 當事務隔離級別為READ COMMITTED時,同一事務下的一致性讀都會建立和讀取此查詢自己的最新的快照

一致性讀是InnoDB在REPEATABLE READ和READ COMMITTED事務隔離中處理SELECT語句的默認模式。一致性讀不會在表上設置任何鎖,所以其它會話可以對表進行讀寫操作。

數據庫狀態(tài)的快照適用于事務中的SELECT語句,而不一定適用于DML語句。如果執(zhí)行INSERT或者UPDATE某些行然后提交該事務,則從另一個并發(fā)REPEATABLE READ事務發(fā)出的DELETE或UPDATE語句則會影響那些剛剛提交的數據行。下面這個示例展示了這種場景:

             Session A                              Session B

           begin;                                   begin;
-------------------------------------------------------------------------------------
           SELECT * FROM t;                        SELECT * FROM t;
           > empty set                             > empty set
          
-------------------------------------------------------------------------------------
                                                   INSERT INTO t (id) VALUES (1);
                                                    > 1 row affected
          
                                                    SELECT * FROM t;
                                                    -----------
                                                    |   id    |
                                                    -----------
                                                    |    1    |
                                                    -----------
-------------------------------------------------------------------------------------            
           SELECT * FROM t;         
           > empty set
-------------------------------------------------------------------------------------                                                    
                                                    COMMIT;
-------------------------------------------------------------------------------------
           SELECT * FROM t;
           > empty set
-------------------------------------------------------------------------------------

           DELETE FROM t WAERE id = 1;
           > 1 row affected
-------------------------------------------------------------------------------------
                                                    SELECT * FROM t;
                                                    -----------
                                                    |   id    |
                                                    -----------
                                                    |    1    |
                                                    -----------
-------------------------------------------------------------------------------------
           COMMIT;
-------------------------------------------------------------------------------------
                                                    SELECT * FROM t;
                                                    > empty set
-------------------------------------------------------------------------------------
           SELECT * FROM t;
           -----------
           |   id    |
           -----------
           |    1    |
           -----------
-------------------------------------------------------------------------------------

一致的讀取不適用于某些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,則讀操作不會再行上加鎖
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容