如何實現(xiàn)事務的隔離性

大家都知道事務的ACID四大特性剃根,其中隔離性代表事務的修改結果在什么時候能被其他事務看到皆的。這篇文章來介紹下數(shù)據(jù)庫中是如何實現(xiàn)事務隔離的找田。

隔離級別介紹

當數(shù)據(jù)庫上有多個事務同時執(zhí)行的時候控轿,就可能出現(xiàn)臟讀(dirty read)、不可重復讀(non reapeatable read)溶浴、幻讀(phantom read)的問題,為了解決這些問題管引,就有了“隔離級別”的概念士败。標準的隔離級別有:讀未提交(read uncommitted)、讀已提交(read commited)褥伴、可重復讀(repeatable read)串行化谅将。其中隔離級別越嚴格,安全性越高重慢,但數(shù)據(jù)庫的并發(fā)性能也就越低饥臂,往往需要在兩者之間找一個平衡點。

隔離的實現(xiàn)

隔離的實現(xiàn)主要有讀寫鎖和MVCC(Multi-Version Concurrency Control)多版本并發(fā)處理方式似踱。

1.讀寫鎖

最簡單直接的的事務隔離實現(xiàn)方式隅熙,每次讀操作需要獲取一個共享鎖,每次寫操作需要獲取一個寫鎖核芽。共享鎖之間不會產(chǎn)生互斥囚戚,共享鎖和寫鎖之間、以及寫鎖與寫鎖之間會產(chǎn)生互斥轧简。當產(chǎn)生鎖競爭時驰坊,需要等待其中一個操作釋放鎖后,另一個操作才能獲取到鎖哮独。

2. MVCC

在讀寫鎖中拳芙,讀和寫的排斥作用大大降低了事務的并發(fā)效率,于是人們又提出了能不能讓讀寫之間也不沖突的方法皮璧,就是讀取數(shù)據(jù)時通過一種類似快照的方式將數(shù)據(jù)保存下來态鳖,這樣讀鎖就和寫鎖不沖突了。不同的事務session會看到自己特定版本的數(shù)據(jù)恶导,即使其他的事務更新了數(shù)據(jù)勉失,但是對本事務仍然不可見艾栋,本事務看到的數(shù)據(jù)始終是第一次查詢到的數(shù)據(jù)。在數(shù)據(jù)庫中,這個快照的處理方式叫多版本并發(fā)控制(Multi-Version Concurrency Control)串远。這種方式真正實現(xiàn)了非阻塞讀螟蝙,只有在寫操作時才需要加行級鎖葡秒,因此并發(fā)效率更高斯入。

在各個數(shù)據(jù)庫系統(tǒng)的,MVCC的實現(xiàn)機制不盡相同蕉拢,下面來詳細介紹一下InnoDB是如何實現(xiàn)MVCC的特碳,主要討論可重復讀級別的實現(xiàn)诚亚。

首先,需要了解兩個概念:ReadView午乓、undo log站宗、可見性判斷算法

ReadView

ReadView其實就是上面提到的快照,每個事務在啟動后第一次執(zhí)行查詢時會創(chuàng)建一份快照益愈,一個事務快照的創(chuàng)建過程可以概括為:

  1. 查看當前所有的未提交并活躍的事務梢灭,存儲在數(shù)組中
  2. 選取未提交并活躍的事務中最小的XID,記錄在快照的xmin中
  3. 選取未提交事務中最大的XID蒸其,記錄快照在xmax中

ReadView主要是用來做可見性判斷的敏释,即通過ReadView可以知道:哪些事務的提交結果對當前事務可見,哪些事務的提交結果對當前事務不可見摸袁。關于如何判斷可見性钥顽,后面部分會對可見性判斷算法做出介紹。不過靠汁,我們可以先思考一個問題蜂大,在可重復讀隔離級別中,哪些事務的提交結果對當前事務可見呢膀曾?

undo log

剛才介紹了ReadView的基礎概念,提到了ReadView是事務的快照阳啥,但是通過ReadView僅僅能知道哪些事務的提交結果對當前事務可見添谊,可是還是不知道當前事務的數(shù)據(jù)快照在哪啊。undo log就是來解決這個問題的察迟。

undo log就是我們通常說的回滾日志斩狱,undo log存放的是數(shù)據(jù)的歷史記錄,也可以叫數(shù)據(jù)的快照扎瓶。
當一個事務要提交修改時:
1.會用排他鎖鎖定該行
2.將該行修改前的值Copy到undo log segment(回滾段)所踊。
3.修改當前行的值,將該行的回滾指針指向undo log中修改前的行概荷。

下圖描述了數(shù)據(jù)行和回滾段的數(shù)據(jù)關系秕岛。

undo log

如上圖,回滾日志使用鏈表組織起來的误证,鏈表的每個節(jié)點都是一個數(shù)據(jù)的版本继薛。InnoDB在每行記錄后面添加了三個字段:
DB_ROW_ID: 包含一個隨著新行插入而單調(diào)遞增的行ID, 當由innodb自動產(chǎn)生聚集索引時,聚集索引會包括這個行ID的值愈捅,否則這個行ID不會出現(xiàn)在任何索引中遏考。
DB_TRX_ID: 最后一次對本行提交修改的事務ID。同時蓝谨,在回滾段中的每條記錄灌具,也包含著該條日志對應的事務ID青团。
DB_ROLL_PTR:指向?qū)懭牖貪L段(rollback segment)的 undo log record (撤銷日志記錄記錄)】ч梗回滾段的數(shù)據(jù)結構是鏈表督笆,如果需要找到指定版本的數(shù)據(jù),需要通過DB_ROLL_PTR指針沿著鏈表遍歷回滾段截歉。

可見性判斷算法

在介紹ReadView的時候胖腾,我們提出了可重復讀隔離級別中事務的可見性問題。這個問題答案很簡單瘪松,在可重復讀隔離級別中咸作,對于當前事務tx_cur來說,tx_cur開始查詢之前的已提交事務都對tx_cur都可見宵睦,在tx_cur開始查詢之前的未提交事務和tx_cur開始查詢之后的所有事務對tx_cur均不可見记罚。下面用一張草圖解釋一下。

可重復讀可見性

如圖所示壳嚎,tx1-tx6分別是按時間順序的6個數(shù)據(jù)庫事務桐智,假設當前啟動的事務是tx_cur,其中tx1-tx2是tx_cur開始查詢之前的已提交事務烟馅,tx3-tx5是tx_cur開始查詢時正在進行的活躍事務说庭,tx6是開始查詢之后的提交的事務。
在tx_cur啟動事務并開始第一次查詢時郑趁,會創(chuàng)建一個ReadView刊驴,ReadView中存儲的是當前正在活躍的所有未提交事務id。在ReadView之前的已提交事務對tx_cur可見寡润,在ReadView中以及ReadView之后的事務對tx_cur均不可見捆憎。

上面是一個簡單的事務可見性判斷過程,那么當前事務該如何找到正確版本的數(shù)據(jù)呢梭纹?這個需要結合undo log一起來說躲惰。

我們可以結合undo log那節(jié)的示意圖來看。
1.首先查詢行的DB_TRX_ID字段变抽,該字段記錄的是當前行最后提交的事務ID础拨,簡稱為tx_id。
2.通過ReadView判斷tx_id是否對tx_cur可見绍载。若可見太伊,即找到了正確版本的數(shù)據(jù);若不可見逛钻,則通過DB_ROLL_PTR指針找到undo log的上一個版本記錄僚焦,重復過程1。

總結

  1. 隔離的實現(xiàn)主要有讀寫鎖和MVCC(Multi-Version Concurrency Control)多版本并發(fā)處理方式曙痘。MVCC方式由于其讀寫不沖突的方式芳悲,相當于讀寫鎖效率更高立肘。
  2. undo log和ReadView通過可見性判斷算法實現(xiàn)了基本的MVCC,從而實現(xiàn)了事務的隔離名扛。
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谅年,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肮韧,更是在濱河造成了極大的恐慌融蹂,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弄企,死亡現(xiàn)場離奇詭異超燃,居然都是意外死亡,警方通過查閱死者的電腦和手機拘领,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門意乓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人约素,你說我怎么就攤上這事届良。” “怎么了圣猎?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵士葫,是天一觀的道長。 經(jīng)常有香客問我送悔,道長慢显,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任放祟,我火速辦了婚禮鳍怨,結果婚禮上呻右,老公的妹妹穿的比我還像新娘跪妥。我一直安慰自己,他們只是感情好声滥,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布眉撵。 她就那樣靜靜地躺著,像睡著了一般落塑。 火紅的嫁衣襯著肌膚如雪纽疟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天憾赁,我揣著相機與錄音污朽,去河邊找鬼。 笑死龙考,一個胖子當著我的面吹牛蟆肆,可吹牛的內(nèi)容都是我干的矾睦。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼炎功,長吁一口氣:“原來是場噩夢啊……” “哼枚冗!你這毒婦竟也來了?” 一聲冷哼從身側響起蛇损,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤赁温,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后淤齐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體股囊,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年床玻,在試婚紗的時候發(fā)現(xiàn)自己被綠了毁涉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡锈死,死狀恐怖贫堰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情待牵,我是刑警寧澤其屏,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站缨该,受9級特大地震影響偎行,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贰拿,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一蛤袒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧膨更,春花似錦妙真、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矗漾,卻和暖如春锈候,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背敞贡。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工泵琳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓获列,卻偏偏與公主長得像琳钉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蛛倦,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容