小白日更第十六天 這篇我們聊MVCC

2021-10-22 14:27:03 字數 2060 閱讀 7015

今天下午和我的好友天文聊起了資料庫的mvcc,多版本併發控制(multi-version concurrency control)資料庫隔離級別,然後就想起來我好像還沒有寫過mysql相關的部落格,吃完飯出去溜達了一會回來就開始寫這篇關於mvcc的文章。

了解mysql的小夥伴應該都知道事務這個詞,而且知道事務有四大特性,我們再鞏固一下:

原子性(atomicity): 事務的最小工作單元,要麼全部成功,要麼全部失敗。

一致性(consistency): 事務開始和結束後,資料庫的完整性不會被破壞。

隔離性(isolation):不同事務之間互不影響,四種隔離級別為ru(讀未提交)、rc(讀已提交)、rr(可重複讀)、serializable (序列化)。

永續性(durability): 事務提交後,對資料的修改是永久性的,即使系統故障也不會丟失。

讀未提交(read uncommitted/ru)

乙個事務讀取了另乙個事務未提交的資料。

這裡我舉個例子,你去銀行取錢,你老婆這個時候正在通過支付寶轉賬。你老婆當前查出來的錢是2000,於是轉走1000,但是還沒有提交事務,你這個時候插卡輸入密碼查出來的錢為2000,那這裡這2000就是髒資料。在這整個過程中,你老婆的事務過程包括了你的事務過程,但是並未執行完全,因此導致了髒資料的產生。

讀已提交(read committed/rc)

又稱為不可重複讀:乙個事務中連續讀取兩次,第二次讀取另乙個事務已經提交update修改的資料(資料改變),兩次讀取到的資料不一致。(一般都是在兩次相同條件下的查詢,但是結果卻不一樣,原因是在第一次讀取之後,其他事務對這個資料進行了修改)

那我們還是緊接著上面的例子講,你先查出來的錢是2000,這時候你老婆轉走1000,並且你老婆的事務提交了,完成。當你取完錢後,再看了一下自己的賬戶餘額,發現不是1000,而是0。因此兩次讀取的資料不一致。導致了不可重複讀的產生。

可重複讀(repeatable read/rr)

又稱為幻讀。就是乙個事務讀取另乙個事務已經提交插入的資料(insert),所以記錄條數已經改變。

上面我們說到的不可重複讀是在兩次相同條件下進行讀取的時候發現資料發生變化,而幻讀多數是也是在相同條件下,只不過這次不是修改資料而是新增資料了,在兩次相同條件下讀取資料憑空比第一次多出了10條資料。驚不驚喜?意不意外?要是發現欠的花唄少了還好,突然莫名其妙不知道上個月什麼時候扣了300塊錢,導致我們要多還300塊錢的花唄,是不是很懵哈哈,這裡舉得例子就是為了方便小夥伴們理解,沒有別的意思嘻嘻~~

序列化(serializable)

在這個隔離級別下只支援單個請求同時執行,所有的操作都需要佇列執行。所以種隔離級別下所有的資料是最穩定的,但是效能也是最差的。資料庫的鎖實現就是這種隔離級別的更小粒度版本。

mvcc會使我們在對資料進行讀取的時候不會對資料進行加鎖,這就大大提高了資料庫的併發處理的能力。

我們使用的mysql預設的儲存引擎是innodb的,那innodb是怎麼實現mvcc的呢?

實際上innodb的mvcc是通過在每行記錄後面儲存兩個隱藏的列來實現的。乙個儲存了行的事務id,乙個儲存了行的回滾指標(就是當我們的事務提交失敗後應該恢復成什麼樣子)

我們在對資料進行查詢的時候innodb只會查詢事務id小於或等於當前事務id的資料行(因為沒開始乙個新的事務,在這行的事務id會自動遞增),這樣就可以確保事務讀取的行,要麼就是在事務開始前已經存在的,要麼是事務自身插入或者修改過的。

我們知道資料庫的併發場景分三種情況:

讀-讀:沒有任何併發的問題

讀-寫:很可能會產生上面提到的髒讀,不可重複讀,幻讀

寫-寫:可能會造成資料覆蓋等問題

那mvcc是就是一種用來解決讀-寫衝突的無鎖併發控制,大概的實現原理,比我我們現在進行插入一條資料,那這個時候就會在這行後面隱式的加上乙個事務的id比如是1,還有乙個回滾指標,第一次插入的時候肯定為null,現在我們對這行資料進行修改,那麼此時事務id會自增+1變成2,而回滾指標指向第一次插入時候的那一行資料。

最後總結一下,innodb使用的事務隔離級別是rc和rr。這兩種隔離級別下的事務在執行普通的 select 操作的時候可以使不同事務的 讀-寫 、 寫-讀 操作併發執行,從而提公升系統效能。

Python 第十六天

魔法方法總是被雙下劃線包圍 例如 init 注 魔法方法第乙個引數為cls 類方法 或者self 例項方法 其中 cls 代表乙個類名稱 self 代表乙個例項物件的名稱 基本方法 init self 構造器,當乙個例項被建立的時候呼叫的初始化方法 new cls 是在乙個物件例項化的時候所呼叫的第...

寒假第十六天

abs x 返回數字的絕對值,如abs 10 返回 10 ceil x 返回數字的上入整數,如math.ceil 4.1 返回 5 cmp x,y 如果 x y 返回 1,如果 x y 返回 0,如果 x y 返回 1 exp x 返回e的x次冪 ex 如math.exp 1 返回2.7182818...

python第十六天

一 包 1 什麼是包?一系列模組的集合 2 有什麼用?包通過資料夾來管理一系列功能相近的模組 3 包重點?包中一定有乙個專門用來管理包中所有模組的檔案 init 4 什麼是包名?包名是存放一系列模組的資料夾名字 5 包名有什麼用 包名 包物件 存放的是管理模組的那個檔案的位址,指向其全域性命名空間。...