跟面试官侃半小时MySQL事务隔离性,从基本概念深入到实现
來源 |?阿丸筆記
提到MySQL的事務(wù),我相信對MySQL有了解的同學(xué)都能聊上幾句,無論是面試求職,還是日常開發(fā),MySQL的事務(wù)都跟我們息息相關(guān)。
而事務(wù)的ACID(即原子性Atomicity、一致性Consistency、隔離性Isolation、持久性Durability)可以說涵蓋了事務(wù)的全部知識點,所以,我們不僅要知道ACID是什么,還要了解ACID背后的實現(xiàn),只有這樣,無論在日常開發(fā)還是面試求職,都能無往而不利。
為了大家更好的閱讀體驗,對ACID的深入分析將分為上下兩篇。
本篇為上篇,主要圍繞ACID中的I,也就是“隔離性”展開,從基本概念,到隔離性的實現(xiàn),最后以一個實戰(zhàn)案例進(jìn)行融會貫通。
嗯,看完全部內(nèi)容你都能理,那跟面試官侃半小時隔離性就沒問題了。
事務(wù)隔離性的基本概念
1.1 什么是ACID中的Isolation,隔離性
Isolation,隔離性,也有人稱之為并發(fā)控制(concurrency control)。事務(wù)的隔離性要求每個事務(wù)讀寫的對象對其他事務(wù)都是相互隔離的,也就是這個事務(wù)提交前,這個事務(wù)的修改內(nèi)容對其他事務(wù)都是不可見的。事務(wù)的隔離性,主要是解決不同事物之間的相互讀寫影響。
所謂的讀寫影響注意分為三種:
臟讀:讀到了別的事務(wù)尚未提交(commit)的變更,別人沒提交,我讀到了。
不可重復(fù)讀:別的事務(wù)提交了變更,被當(dāng)前事務(wù)讀到了。然后導(dǎo)致本事務(wù)多次select的結(jié)果不一樣,讀到了別的事務(wù)提交的內(nèi)容。
幻讀:也是讀到了別的事務(wù)提交的內(nèi)容,但是跟上面的不同之處在于,讀到了原本不存在的記錄。
注意,不可重復(fù)讀,主要是讀到了別的事務(wù)update的內(nèi)容。而幻讀,是讀到了別的事務(wù)insert的內(nèi)容。
1.2 隔離性的隔離級別
為了解決事務(wù)隔離性的問題,數(shù)據(jù)庫一般會有不同的隔離級別來解決相應(yīng)的讀寫影響。
讀未提交:一個事務(wù)B還沒提交,它的修改就被別的事務(wù)A讀到了。
讀已提交:一個事務(wù)B提交后,它的修改被其他事務(wù)A看到了。
可重復(fù)讀:一個事物B提交前和提交后,事務(wù)A都無法讀到事務(wù)B的變更。
串行化:對同一行記錄,當(dāng)出現(xiàn)不同事物的讀寫沖突時,是通過串行化的方式解決的,后一個事務(wù)必須等前一個事務(wù)完成才能執(zhí)行。
不同隔離級別能夠解決不同的隔離性問題。
需要注意的是,這是標(biāo)準(zhǔn)事務(wù)隔離級別的定義。在MySQL的innodb引擎中,在可重復(fù)讀級別下,通過mvcc解決了幻讀的問題,具體實現(xiàn)我們后面再講。
同時,需要注意的是,到目前為止,我們說的讀,都是”快照讀”,普通的select。后面我們還會提到“當(dāng)前讀”,是不一樣的哦。
事務(wù)隔離性的實現(xiàn)
要實現(xiàn)事務(wù)的隔離性,需要了解兩個方面的內(nèi)容,一個是鎖,一個是多版本并發(fā)控制(MVCC)。
2.1 事務(wù)的行鎖
InnoDB中,實現(xiàn)了兩種標(biāo)準(zhǔn)的行級鎖:
共享鎖(S Lock),也叫讀鎖,允許事務(wù)讀取一行數(shù)據(jù)。
排它鎖(X Lock),也叫寫鎖,允許事務(wù)刪除或者更新一行數(shù)據(jù)(注意,這里沒有提到插入哦,插入涉及到幻讀,可以看文章最后的說明)
普通select語句不會有任何鎖,那么如何獲得共享鎖和排它鎖呢?
Select … lock in share mode語句能夠獲得共享鎖
Select … for update(特殊的select,用mysql簡單實現(xiàn)分布式鎖經(jīng)常用它)、Update、delete語句能夠獲得排它鎖
當(dāng)一個事務(wù)A已經(jīng)獲得了行r的共享鎖,那么另一個事務(wù)B可以立刻獲得行r的共享鎖,因為不會改變r的數(shù)值,這種叫做鎖兼容。
如果這時候有事務(wù)C希望獲得行r的排它鎖,那么就必須等待事務(wù)A和事務(wù)B釋放行r的共享鎖之后,才能獲得排它鎖,這種叫做鎖不兼容。
普通的select不會對行上鎖,而select…lock in share mode會上共享鎖,select…for update會上排它鎖。
對于普通的select的讀取方式,稱為”快照讀“,也叫”一致性非鎖定讀“。
對于帶鎖的select讀取,或者update tb set a = a+1(讀取a的當(dāng)前值),稱為“當(dāng)前讀”,也叫“一致性鎖定讀”。
如果在update、insert的時候,不能進(jìn)行select,那么服務(wù)的并發(fā)訪問性能就太差了。因此,我們?nèi)粘5牟樵?#xff0c;都是“快照讀”,不會上鎖,只有在update\insert\“當(dāng)前讀”的時候,才會上鎖。而為了解決“快照讀”的并發(fā)訪問問題,就引入了MVCC。
2.2 多版本并發(fā)控制MVCC
如果說上面的行鎖是一種悲觀鎖,那么MVCC就是一種樂觀鎖的實現(xiàn)方式,而且是一種很常用的樂觀鎖實現(xiàn)方式。
所謂多版本,就是一行記錄在數(shù)據(jù)庫中存儲了多個版本,每個版本以事務(wù)ID作為版本號。InnoDB 里面每個事務(wù)有一個唯一的事務(wù) ID,是在事務(wù)開始的時候向InnoDB的事務(wù)系統(tǒng)申請的,并且按照申請順序嚴(yán)格遞增的。假如一行記錄被多個事務(wù)更新,那么,就會產(chǎn)生多個版本的記錄。
以某一行數(shù)據(jù)作為例子:
經(jīng)過兩次事務(wù)的操作,value從22變成了19,同時,保留了三個事務(wù)id,15、25、30。
在每個記錄多版本的基礎(chǔ)上,需要利用“一致性視圖”,來做版本的可見性判斷。
這里,我們要區(qū)分MySQL里面的兩個”視圖”概念:
一個是view,通過語法create view … 實現(xiàn),主要創(chuàng)建一個虛擬表,用來執(zhí)行查詢語句。
一個是InnoDB用來實現(xiàn)mvcc的一致性視圖(consistent read view),純邏輯概念,沒有物理結(jié)構(gòu),定義了在事務(wù)期間,你能看到哪些版本的數(shù)據(jù)。
我們?nèi)奶岬降摹耙晥D”都是第二種,主要是支持InnoDB在“讀已提交”和“可重復(fù)讀”級別的并發(fā)訪問問題。
“讀未提及”級別下,沒有一致性視圖
“讀已提交”級別下,會在?每個SQL開始執(zhí)行的時候?創(chuàng)建一致性視圖
“可重復(fù)讀”級別下,會在?每個事務(wù)開始的時候?創(chuàng)建一致性視圖
“串行化”級別下,直接通過加鎖避免并發(fā)問題
下面,我們簡單介紹一下創(chuàng)建一致性視圖的邏輯。
以“可重復(fù)讀”級別為例。
當(dāng)一個事務(wù)開啟的時候,會向系統(tǒng)申請一個新事務(wù)id
此時,可能還有多個正在進(jìn)行的其他事務(wù)沒有提交,因此在瞬時時刻,是有多個活躍的未提交事務(wù)id
將這些未提交的事務(wù)id組成一個數(shù)組,數(shù)組里面最小的事務(wù)id記錄為低水位,當(dāng)前系統(tǒng)創(chuàng)建過的事務(wù)id的最大值+1記錄為高水位
這個數(shù)組array 和 高水位,就組成了“一致性視圖”。
有了一致性視圖后,我們就可以判斷一行數(shù)據(jù)的多版本可見性了,無論是“讀已提交”還是“可重復(fù)讀”級別,可見性判斷規(guī)則是一樣的,區(qū)別在于創(chuàng)建快照(一致性視圖)的時間。
在當(dāng)前事務(wù)中,讀取其他某一行的記錄,對其中的版本號的可見性判斷有五種情況(建議自己跟著捋一捋,挺重要的):
如果版本號小于“低水位”,說明事務(wù)已經(jīng)提交,那肯定 可見;
如果版本號大于“高水位”,說明這行數(shù)據(jù)的這個事務(wù)id版本是在快照后產(chǎn)生的,那肯定 不可見;
如果版本號在事務(wù)數(shù)組array中,說明這個事務(wù)還沒提交,所以 不可見;
如果版本號不在事務(wù)數(shù)組array中,且低于高水位,說明這個事務(wù)已經(jīng)提交,所以 可見;
當(dāng)然,無論什么時候,自己的事務(wù)id中的任何變化,都是可見的
可以看看下面這個例子,更容易理解。
系統(tǒng)創(chuàng)建過的事務(wù)id:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
事務(wù)A啟動,拍個快照
此時未提交的事務(wù)id有:7,8,9
一致性視圖:數(shù)組array[7,8,9] + 高水位16(15+1)
對于任意一行數(shù)據(jù)的可見性判斷:
小于7的,可見
大于16的,說明是快照后產(chǎn)生的,不可見
10-15,不在數(shù)組array中,說明已經(jīng)提交了,可見
7,8,9在array中,說明未提交,不可見
兩個重要結(jié)論:
InnoDB 利用了“所有數(shù)據(jù)都有多個版本”的這個特性,實現(xiàn)了“秒級創(chuàng)建快照”的能力。
MVCC的實現(xiàn),就是根據(jù)當(dāng)前事務(wù)的事務(wù)id為依據(jù)創(chuàng)建“一致性視圖”,利用一致性視圖來判斷數(shù)據(jù)版本的可見性。
隔離性實戰(zhàn)
下面,我們來兩個實戰(zhàn)案例,將上面的基礎(chǔ)概念與實現(xiàn)融會貫通吧。
1)并發(fā)select&update 案例
id=1 的value初始為1。
我們看下,在不同隔離級別,Time5、Time7、Time9事務(wù)A查詢到的value 分布為多少。
“讀未提交”:2,2,2
“讀以提交”:1,2,2
“可重復(fù)讀”:1,1,2
串行化:1,1,2(注意,這里在事務(wù)A提交前,事務(wù)B都會阻塞,直到事務(wù)A提交后才能執(zhí)行)
2)并發(fā)update案例
id=1 的value初始為1,在可重復(fù)讀級別:
我們看一下,你猜猜事務(wù)A和事務(wù)B讀取的value是多少?
答案是:1 和 3
可能會產(chǎn)生困惑,事務(wù)A在啟動后快照,所以讀到了1是正常的,但是事務(wù)2在啟動的時候快照了,然后在自己的事務(wù)中+1,怎么會讀到3而不是2呢?
原因很簡單,即使是在可重復(fù)讀的級別,事務(wù)?更新數(shù)據(jù)?的時候,只能用當(dāng)前讀(想想也能理解,不然update就出現(xiàn)數(shù)據(jù)不一致了)。
如果當(dāng)前的記錄的行鎖被其他事務(wù)占用的話,就需要進(jìn)入鎖等待。而讀提交的邏輯和可重復(fù)讀的邏輯類似,它們最主要的區(qū)別是:在可重復(fù)讀隔離級別下,只需要在事務(wù)開始的時候創(chuàng)建一致性視圖,之后事務(wù)里的其他查詢都共用這個一致性視圖;在讀提交隔離級別下,每一個語句執(zhí)行前都會重新算出一個新的視圖。
這里,我們需要注意的是事務(wù)的啟動時機(jī)。
begin/start transaction 命令并不是一個事務(wù)的起點,在執(zhí)行到它們之后的第一個操作 InnoDB 表的語句,事務(wù)才真正啟動,一致性視圖是在執(zhí)行第一個快照讀語句時創(chuàng)建的。
如果你想要馬上啟動一個事務(wù),可以使用 start transaction with consistent snapshot 這個命令,一致性視圖是在執(zhí)行 start transaction with consistent snapshot 時創(chuàng)建的。
關(guān)于幻讀
前文已經(jīng)提到了,對于普通數(shù)據(jù)庫,需要到可串行化的隔離級別才能解決幻讀問題。
而對于InnoDB存儲引擎來說,在可重復(fù)讀級別下就能解決幻讀問題。
InnoDB存儲引擎有三種行鎖算法:
行鎖:當(dāng)個行記錄上的鎖
間隙鎖:Gap Lock,鎖定一個范圍,但不包含記錄本身
Next-Key Lock:就是行鎖+間隙鎖,同時鎖上一個范圍,并且鎖定記錄本身
InnoDB就是通過Next-Key Lock解決了幻讀的問題。
好了,關(guān)于ACID的隔離性就說到這里,你有什么看法,歡迎在評論區(qū)和我們討論。
「AI大師課」是CSDN發(fā)起的“百萬人學(xué)AI”倡議下的重要組成部分,4月份AI大師課以線上技術(shù)峰會的形式推出,來自微軟、硅谷TigerGraph、北郵等產(chǎn)學(xué)界大咖就圖計算+機(jī)器學(xué)習(xí),語音技術(shù)、新基建+AI、AI+醫(yī)療等主題展開分享,掃描下方二維碼免費(fèi)報名,限時再送299元「2020AI開發(fā)者萬人大會」門票一張。
推薦閱讀:一文教你如何使用 MongoDB 和 HATEOAS 創(chuàng)建 REST Web 服務(wù) 一個數(shù)據(jù)科學(xué)家需要哪些核心工具包? AI 開發(fā)者不容錯過的 20 個機(jī)器學(xué)習(xí)和數(shù)據(jù)科學(xué)網(wǎng)站 馬云為什么救援世界? 1分鐘售出5萬張票!電影節(jié)搶票技術(shù)揭秘 BTC重現(xiàn)“自由落體”式暴跌,原來是受這幾個因素影響? 真香,朕在看了!總結(jié)
以上是生活随笔為你收集整理的跟面试官侃半小时MySQL事务隔离性,从基本概念深入到实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 七大新品集中亮相,腾讯云AI大数据全线升
- 下一篇: linux cmake编译源码,linu