理解MySQL InnoDB事務隔離級別

2021-09-18 06:10:09 字數 2514 閱讀 1842

本文為翻譯的文章,作者ovais.tariq,原文:

隔離性是acid性質中很重要的部分,它保證事務以一種可靠的方式進行處理。隔離性確保同時執行的事務不會相互干擾。隔離性保證資料的一致性。如果事務沒有被隔離,那麼某個事務可能會修改其它事務正在讀取的資料,因而產生了資料的不一致。

既然我們理解了隔離性是什麼,讓我們來掌握隔離級別。隔離級別決定了事務之間如何被隔離,它可能是沒有任何的隔離或者最高端別的讓事務序列化執行的級別。選擇合適的隔離級別確實依賴於程式的需求,但你首先必須理解所有的隔離級別以及選擇任何一種所產生的後果。

innodb支援所有4種sql標準的隔離級別,列舉如下 :

read uncommitted

read-uncommitted隔離級別在事務之間根本沒有太多的隔離性。事務可以看到其他事務還沒有提交的資料修改。這意味著事務可能會讀到不存在的資料,因為其它正在更新資料的事務回滾了,並沒有提交。這就是髒讀。很少有應用需要依賴髒讀,實際上這不能算是一種隔離級別。簡言之,它根本就沒有任何的隔離性,這樣的系統實際上也不能被稱為乙個事務性的系統。

read committed

read-committed隔離級別避免了髒讀的現象,因為沒有提交的修改對其它事務都是不可見的,直到修改被提交。在這樣的隔離級別中,每個select語句都使用在執行前已提交資料的快照。因為每個select語句都有自己的快照,所以相同的select語句在同乙個事務的不同時間執行,可能會返回不同的結果集。這種現象被稱為不可重複讀。

repeatable read

repeatable-read隔離級別避免了不可重複讀的現象。在事務執行的整個期間,相同的select語句不管執行多少次都會返回相同的結果集。select語句的快照在第一次執行的時候就記下來了,相同的select語句在整個事務執行期間都使用同樣的快照。在這種隔離級別中執行的事務,不考慮其它事務對資料所做的任何改變。這確保了資料讀取總是一致的(可重複的)。它是innodb預設的隔離級別。儘管這種隔離級別解決了不可重複讀的問題,但仍然可能有幻讀的問題。

serializable

serializable隔離級別避免了幻讀的現象。執行在這個隔離級別中的事務,會在所有訪問的資料行上加鎖,同時鎖住資源,這樣就不能向事務操作的表新增記錄。事務在這種情況下是以序列化的方式執行。這種隔離級別是最強的。

serializable隔離級別幾乎可以規避

就像上面描述的,serializable只能幫助你避免幻讀的問題,在其它方面,serializable幾乎與repeatable-read完全一樣。innodb有一種特殊的被稱為間隙鎖的功能,能夠幫助你避免幻讀問題。間隙鎖會在索引記錄之間加鎖,也可能是在第一條索引記錄之前或最後一條索引記錄之後的區間加上鎖。為了避免幻讀,所有你需要做的事情是使用select…for update或者lock in share mode來加上讀鎖。

鎖與隔離級別

read-uncommitted隔離級別加的鎖最少,隨後是read-committed,它消除了大部分的間隙鎖,因而產生死鎖的情況較少,另外,read-committed只在讀取的索引記錄上加鎖,而不是在這些記錄的前後區間加鎖。repeatable-read與read-committed相比,有更高層級的加鎖。update,delete使用鄰鍵鎖,同時,讀鎖也使用鄰鍵鎖。serializable有最高端別的鎖,所有簡單的select語句都自動轉化成select…lock in share mode,因而所有的記錄都有共享鎖。

複製與隔離級別

mysql預設的複製型別是基於語句的複製,這種複製型別會在從伺服器上重新執行在主伺服器執行過的語句,通過這種方式同步資料更新。這需要更嚴格的隔離級別(使用更多的鎖),把同樣的sql在從伺服器上執行,以這樣的方式來達到資料更新的一致性。就像上面提到的,read-committed製造了不可重複讀的場景,因而它對於基於語句的複製是不安全的。所以,要使用repeatable-read或者serializable隔離級別來進行基於語句的複製。如果你的mysql版本大於等於5.1,那麼你可以使用read-committed來進行基於行的複製,因為基於行的複製的話,每一行資料改變的確切資訊你都有。

效能與隔離級別

正如我在「鎖與隔離級別」章節中提到的,serializable和repeatable-read使用了大量的鎖,從而產生更多死鎖的情況,反而過來降低了效能。事實上,serializable是效能最差的隔離級別,因為它甚至把普通的讀取都轉換成了加鎖讀。repeatable-read在鎖和死鎖方面要好一些,但read-committed更好,因為它有更少的間隙鎖。但是鎖和死鎖不是效能方面唯一要都考慮的事情,互斥鎖爭用的問題也需要考慮。mark callaghan有一篇文章,在互斥鎖爭用的上下文中比較了repeatable-read和read-committed。

結論我嘗試對四種隔離級別,以及如何使用它們的前因後果進行了詳盡地描述,我也提到了與隔離級別有關的鎖和效能。現在,實際上你只有read-commited和repeatable-read這兩種選擇。這種選擇實際上基於你的程式的型別。我不認為任何通用的基準能幫助你在這兩個當中做出選擇。所以在做出任何決定前,先執行程式特定的基準然後再嘗試做出決定。我也由衷地希望你執行的mysql版本大於等於5.1,因為在其它任何版本上,repeatable-read幾乎是你唯一的選擇。

Mysql InnoDB 事務簡單理解

1.事務基本特性 acid a 由undo 來實現的 i 由鎖實現 d 由redo實現 c 由aid共同保證 2.undo 實現了 事務的回滾 以及 mvcc 事務的回滾 記錄下事務期間的所有update delete insert操作的前後value,當需要rollback時會做乙個相反的操作。m...

MySQL InnoDB事務模型

事務的acid特性 原子性 一致性 隔離性 永續性。這部分不多說了,任何一本講資料庫理論的書籍裡邊都會有講。mysql innodb通過鎖來實現事務的一致性和隔離性,共實現了四種事務隔離級別 read uncommitted讀取未提交 某個session中的事務可以看到其他session的事務中尚未...

Mysql InnoDB事務隔離級別

隔離級別 髒讀 dirty read 不可重複讀 nonrepeatable read 幻讀 phantom read 未提交讀 read uncommitted 可能可能 可能已提交讀 read committed 不可能可能 可能可重複讀 repeatable read 不可能不可能 可能可序列...