MySQL 到底是如何做到多版本併發的?

2022-09-21 10:03:11 字數 1644 閱讀 3725

目錄

我們知道,讀未提交會造成髒讀、幻讀、不可重複讀,讀已提交會造成幻讀、不可重複讀,可重複讀可能會有幻讀,和序列化就不會有這些問題。

那 innodb 到底是怎麼解決這些問題的呢?又或者,你有沒有想過造成髒讀、幻讀、不可重複讀的底層最根本的原因是什麼呢?

這就是今天要聊的主角——mvcc(multi-version concurrent controll),也叫多版本併發控制。innodb 是乙個支援多事務併發的儲存引擎,它能讓資料庫中的讀-寫操作能夠併發的進行,避免由於加鎖而導致讀阻塞。

正是由於有了 mvcc,在事務b更新程式設計客棧 id=1 的資料時,事務a讀取 id=1 的操作才不會被阻塞。而不阻塞的背後則是不加鎖的一致性讀。那什麼是一致性讀?

1、一致性讀

簡單來講,當進行 query 查詢時,innodb 會對當前時間點的資料庫建立乙個快照,快照建立完之後,當前查詢就只能感知到快照建立之前提交的事務改動,在快照建立之後再提交的事務就不會被當前query感知。

當然,當前事務自己更新的資料是個例外。當前事務修改過的行,再次讀取時是能夠拿到最新的資料的。而對於其他行,讀取的仍然是打快照時的版本。

而這個快照就是 innodb 實現事務隔離級別的關鍵。

在讀已提交(read committed)的隔離級別下,事務中的每一次的一致性讀都會重新生成快照。而在可重複讀(repeatable read)的隔離級別下,事務中所有的一致性讀都只會使用第一次一致性讀生成的快照。

這也就是為什麼,在上圖中事務b提交了事務之後,讀已提交的隔離級別下能看到改動,可重複讀的隔離級別看不到改動,本質上就是因為讀已提交又重新生成了快照。

在讀已提交、可重複讀的隔離級別下,select 語句都會預設走一致性讀,並且在一致性讀的場景下,不會加任何的鎖。其他的修改操作也可以同步的進行,大大的提公升了 mysql 的效能。而這也就是mvcc多版本併發控制的實現原理。這種讀還有個名字叫快照讀。

那如果我在事務中想要立馬看到其他的事務的提交怎麼辦?有兩種方法:

(1)使用讀已提交隔離級別

(2)對select加鎖,共享鎖和排他鎖都行,再具體點就是for share和for update

當然,程式設計客棧第二種方法如果對應的記錄加的鎖和select加的鎖互斥,select就會被阻塞,這種讀也有個別名叫當前讀。

了解完上面的解釋,下次再有人問你 mvcc 是怎麼實現的,你就能從一致性讀(快照讀)和當前讀來進行解釋了,並且把不同的隔離級別下對一致性讀快照的重新整理機制也講清楚。

但是我覺得還不夠,應該還需要繼續往下深入了解。因為我們只知道個快照,其底層到底是怎麼實現的呢?其實還是不知道的。

2、深入一致性讀原理

從常理來說,不同的一致性讀可能會讀到不同版本的資料,那麼這些肯定都儲存在 mysql 中的,否則不可能被讀取到。是的,這些資料都儲存在 innodb 的表空間內,再具體點這些資料儲存在 undo 表空間內。

innodb 內實現 mvcc 的關鍵其實就是三個字段,並且資料表中每一行都有這三個字段:

通過 db_roll_ptr 可以拿到最新的一條 undo log,然後每乙個對應的 undo log 指向其上乙個 undo log,這樣一來,不同的版本就可以連線起來形成鍊錶,不同的事務根據需求和規則,從鍊錶中www.cppcns.com選擇不同的版本進行讀取,從而實現多版本的併發控制,如下圖:

可能有人對 undo log 沒啥概念,記住這個就好了:

MySQL是如何做到安全登陸

首先mysql的密碼許可權儲存在mysql.user表中。我們不關注鑑權的部分,我們只關心身份認證,識別身份,後面的許可權控制是很簡單的事情。在mysql.user表中有個authentication string欄位,儲存的是密碼的兩次sha1值。你可以用下面的語句,驗證和mysql.user表中...

到底是寬字元還是多字元?到底是寬位元組還是多位元組?

多位元組 multibyte 寬字元 widechar 非英語系的大部分語言,存在無法用有限的ascii字元表達的問題。由此產生了使用多位元組字元來表示的辦法,比如gb編碼的漢字。但多位元組帶來的乙個顯著不便就是多位元組字元在處理的時候不太方便。比如文字編輯的時候,中英文混排,游標移動 漢字刪除時會...

web網頁劫持是如何做到的

按照劫持的方法不同,我將劫持分為下面兩類 為了區分哪些是第三方給予導流過來的,通常會在url位址增加類似source from之類的引數,或者進入頁面之前通過 中間頁 種cookie。這樣,當使用者輸入乙個正常 的時候,劫持方會在網路層讓其跳轉到帶分成或者渠道號的 中間頁 或者帶渠道號的頁面。這樣使...