一直在使用mysql, 但是對(duì)于mysql 的一些核心原理一直有些模糊媚狰。出問(wèn)題總是想著公司有專(zhuān)職的DBA, 專(zhuān)業(yè)的事情交給專(zhuān)業(yè)的人來(lái)做嘛淫僻,所以一直沒(méi)有研究(其實(shí)主要是懶)。趁著假期壶唤,閑著也是閑著雳灵,就想簡(jiǎn)單了解一下。人嘛闸盔,總是嫌麻煩悯辙,總想找些現(xiàn)成的文章或者課程。找了極客時(shí)間的兩套mysql相關(guān)課程 (基礎(chǔ))SQL必知必會(huì)迎吵、(進(jìn)階)MySQL實(shí)戰(zhàn)45講躲撰,看了個(gè)大概,只總結(jié)出來(lái)mysql最核心的應(yīng)該是事務(wù)跟索引击费。
但是看完之后拢蛋,思維陷入了混亂,每一節(jié)都是一些知識(shí)點(diǎn)的堆積蔫巩,沒(méi)有形成體系谆棱,自己想不明白彼此之間到底是什么關(guān)系。自己又找了拉鉤上的《高性能mysql實(shí)戰(zhàn)》圆仔,有個(gè)大概了础锐。我整理了兩個(gè)核心問(wèn)題 :1、“事務(wù)的特性是如何實(shí)現(xiàn)的荧缘?”皆警;2、“事務(wù)四種隔離級(jí)別是怎么結(jié)合鎖來(lái)解決并發(fā)產(chǎn)生的三種經(jīng)典問(wèn)題的截粗?” 信姓。
本文是mysql 事務(wù)的第一部分-四個(gè)特性及實(shí)現(xiàn)。自己不是專(zhuān)職的DBA绸罗,理解難免有偏差意推,只是簡(jiǎn)單地總結(jié)一下。希望對(duì)你有所幫助珊蟀,如果有紕漏菊值,也請(qǐng)留言指出,感謝~
文章主要內(nèi)容如下:
- 事務(wù)的定義
- 事務(wù)的四個(gè)特性以及背后的技術(shù)原理
1 事務(wù)是什么
做工程實(shí)現(xiàn)育灸,想必大家都接觸過(guò)事務(wù)腻窒。事務(wù),一組邏輯執(zhí)行單元磅崭,要么全部做完儿子,要不都不做,不會(huì)處于一個(gè)中間狀態(tài)砸喻。事務(wù)是為了保證DB操作正確性跟完整性的保障柔逼。
2 事務(wù)的四個(gè)特性
按照上一小節(jié)的描述蒋譬,更多的像是在描述事務(wù)原子性這一特性。其實(shí)事務(wù)并不僅僅是只有原子性這一個(gè)特性愉适。是由四部分組成 ACID犯助。下面我們介紹一下這部分:
2.1 原子性(Atomicity)
原子性:事務(wù)的所有操作,要么全部完成维咸,要么全部不完成也切,不會(huì)結(jié)束在某個(gè)中間環(huán)節(jié)。
這個(gè)是最基本的要求腰湾。
2.2 一致性(Consistency)
一致性:事務(wù)完成之后,事務(wù)所做的修改進(jìn)行持久化保存疆股,不會(huì)丟失费坊。
一致性更像是其他三個(gè)特性綜合之后的結(jié)果。需要依賴(lài)于它們旬痹。一致性可以從兩個(gè)角度思考:一個(gè)是約束的一致性(比如主鍵附井、外鍵約束),另一種是業(yè)務(wù)邏輯上的一致性两残。
2.3 隔離性(Isolation)
隔離性:當(dāng)多個(gè)事務(wù)并發(fā)訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)中的同一數(shù)據(jù)時(shí)永毅,所表現(xiàn)出來(lái)的相互關(guān)系。
隔離性關(guān)系到多個(gè)事務(wù)并發(fā)操作時(shí)數(shù)據(jù)的準(zhǔn)確性人弓。innodb有四個(gè)常見(jiàn)的隔離性沼死,這些隔離性會(huì)借助于鎖機(jī)制 解決一些并發(fā)常見(jiàn)的問(wèn)題。當(dāng)然崔赌,因?yàn)楦綦x性強(qiáng)弱的不同意蛀,有些問(wèn)題在某些場(chǎng)景下是解決不了的。下一節(jié)健芭,我們將重點(diǎn)講解這個(gè)問(wèn)題县钥。
2.4 持久性(Durability)
持久性:事務(wù)開(kāi)始之前和事務(wù)結(jié)束之后,數(shù)據(jù)庫(kù)的完整性限制未被破壞慈迈。
這兒主要是指持久化的問(wèn)題若贮。數(shù)據(jù)寫(xiě)入之后,要保證不會(huì)丟失痒留,在系統(tǒng)崩潰之后谴麦,也能恢復(fù)。
3 四個(gè)特性背后是怎么實(shí)現(xiàn)的伸头?
大多數(shù)的文章细移,講完事務(wù)的四個(gè)特性就結(jié)束了。如果只是停留在這個(gè)層面熊锭,我們就沒(méi)有寫(xiě)這篇文章的必要了弧轧。在這部分雪侥,我們會(huì)講解一下四個(gè)特性是如何實(shí)現(xiàn)的?在講解特性實(shí)現(xiàn)原理之前精绎,我們先講一下用到的幾個(gè)知識(shí)點(diǎn)速缨。
3.1 redo、undo與binlog
3.1.1 redo
redo代乃, 重做日志旬牲,保證了事務(wù)的原子性與持久性。通常是物理日志搁吓,用于恢復(fù)事務(wù)修改的頁(yè)操作原茅。
redo 包括兩部分:
- 1 內(nèi)存中的重做日志緩沖,易失堕仔,一般在事務(wù)開(kāi)始時(shí)擂橘,就要寫(xiě)入這部分
- 2 第二部分是重做日志,這個(gè)是要刷如磁盤(pán)的摩骨。一般在事務(wù)提交時(shí)會(huì)刷如磁盤(pán)通贞。有些場(chǎng)景,也可以設(shè)置沒(méi)用每次事務(wù)提交就刷恼五,而是交給master thread 定期刷盤(pán)昌罩,但是這樣如果在這期間,宕機(jī)了灾馒,則沒(méi)有刷盤(pán)的數(shù)據(jù)就要丟失了茎用。
redo 日志里面存儲(chǔ)的是操作指令,每個(gè)指令根據(jù)操作類(lèi)型的不同睬罗,存儲(chǔ)格式也是不同的绘搞。
redo 在內(nèi)存中,結(jié)合了checkpoint 以及LSN(log sequence number) 來(lái)保證刷入磁盤(pán)的數(shù)據(jù)不丟傅物。checkpoint記錄了刷磁盤(pán)刷到哪兒了夯辖,LSN記錄了當(dāng)前內(nèi)存中的日志編號(hào)。二者之間的內(nèi)容就是沒(méi)有刷新到磁盤(pán)的日志董饰。
3.1.2 undo
undo保證了事務(wù)的一致性蒿褂。undo 并不是物理日志,而是邏輯上的日志卒暂,有一個(gè)專(zhuān)門(mén)的內(nèi)存字段存儲(chǔ)undo 日志啄栓。
undo 主要有兩個(gè)作用:1是回滾操作,將數(shù)據(jù)庫(kù)邏輯地恢復(fù)到原來(lái)的樣子也祠,但是已經(jīng)分配的頁(yè)昙楚、或者數(shù)據(jù)結(jié)果可能回滾不了了; 2 是MVCC(多版本并發(fā)控制)诈嘿,實(shí)現(xiàn)并發(fā)控制的一種很通用的機(jī)制堪旧,在下面的一節(jié)中削葱,我們會(huì)講到。
當(dāng)事務(wù)提交的時(shí)候淳梦,innodb不會(huì)立即刪除undo log析砸,因?yàn)楹罄m(xù)還可能會(huì)用到undo log,如隔離級(jí)別為repeatable read時(shí)爆袍,事務(wù)讀取的都是開(kāi)啟事務(wù)時(shí)的最新提交行版本首繁,只要該事務(wù)不結(jié)束,該行版本就不能刪除陨囊,即undo log不能刪除弦疮。
但是在事務(wù)提交的時(shí)候,會(huì)將該事務(wù)對(duì)應(yīng)的undo log放入到刪除列表中蜘醋,未來(lái)通過(guò)purge來(lái)刪除胁塞。并且提交事務(wù)時(shí),還會(huì)判斷undo log分配的頁(yè)是否可以重用堂湖,如果可以重用,則會(huì)分配給后面來(lái)的事務(wù)状土,避免為每個(gè)獨(dú)立的事務(wù)分配獨(dú)立的undo log頁(yè)而浪費(fèi)存儲(chǔ)空間和性能无蜂。
3.1.3 binlog
binlog基本定義:二進(jìn)制日志,也成為二進(jìn)制日志蒙谓,記錄對(duì)數(shù)據(jù)發(fā)生或潛在發(fā)生更改的SQL語(yǔ)句斥季,并以二進(jìn)制的形式保存在磁盤(pán)中;
作用:Mysql的作用類(lèi)似于ORACLE的歸檔日志累驮,可以用來(lái)查看數(shù)據(jù)庫(kù)的變更歷史(具體的時(shí)間點(diǎn)所有的SQL操作)酣倾、數(shù)據(jù)庫(kù)增量備份和恢復(fù)(增量備份和基于時(shí)間點(diǎn)的恢復(fù))、Mysql的復(fù)制(主主數(shù)據(jù)庫(kù)的復(fù)制谤专、主從數(shù)據(jù)庫(kù)的復(fù)制)
3.1.4 更新操作中 redolog 與 binlog的順序
3.2 WAL (write ahead logging) 又稱(chēng) ARIES三原則
ARIES三原則躁锡,是指write ahead logging。
1 先寫(xiě)日之后寫(xiě)磁盤(pán)置侍,日志成功寫(xiě)入后就不會(huì)丟失映之,后續(xù)由checkpoint機(jī)制來(lái)保證磁盤(pán)物理文件與redo日志達(dá)到一致性。
2 利用Redo 記錄變更后的數(shù)據(jù)蜡坊,即redo記錄事務(wù)數(shù)據(jù)變更后的值
3 利用Undo 記錄變更前的數(shù)據(jù)杠输,用于回滾和其他事務(wù)多版本讀。
3.3 特性的實(shí)現(xiàn)
3.3.1 各特性間的關(guān)系
在講解具體實(shí)現(xiàn)之前秕衙,我們先來(lái)張圖蠢甲,參考自 《高性能mysql實(shí)戰(zhàn)》
3.3.2 原子性的實(shí)現(xiàn)
每一個(gè)寫(xiě)事務(wù),都會(huì)修改 Buffer Pool据忘,從而產(chǎn)生相應(yīng)的 Redo 日志鹦牛,這些日志信息會(huì)被記錄到 ib_logfiles 文件中搞糕。因?yàn)?Redo 日志是遵循 Write Ahead Log 的方式寫(xiě)的,所以事務(wù)是順序被記錄的能岩。
任何 Buffer Pool 中的頁(yè)被刷到磁盤(pán)之前寞宫,都會(huì)先寫(xiě)入到日志文件中。
回滾(undo日志)
要保證原子性拉鹃,就必須在異常發(fā)生時(shí)辈赋,對(duì)已經(jīng)執(zhí)行的操作進(jìn)行回滾,此時(shí)就用到了undo 日志
膏燕。
未刷盤(pán)數(shù)據(jù)提交(redo日志)
除了回滾之外钥屈,還有一種場(chǎng)景是事務(wù)提交了,日志寫(xiě)入到buffer pool 了坝辫,但是buffer pool的臟頁(yè) 并沒(méi)有刷盤(pán)篷就,那此時(shí)怎么恢復(fù)呢?就需要用到redo日志恢復(fù)數(shù)據(jù)近忙。
綜合上述兩種case竭业,其實(shí)原子性的保證就是用到了WAL的原則。
3.3.3 持久性的實(shí)現(xiàn)
持久性是表示一個(gè)事務(wù)一旦提交及舍,它對(duì)數(shù)據(jù)的改變就是永久的未辆。通過(guò)原子性可以保證的一旦事務(wù)提交,即使遇到宕機(jī)锯玛,也可以從邏輯上將數(shù)據(jù)找回來(lái)咐柜,再次寫(xiě)入到物理存儲(chǔ)空間。
因?yàn)閞edo日志是有限的攘残,那么宕機(jī)之后拙友,redo日志之前的數(shù)據(jù)怎么恢復(fù)呢,這就結(jié)合binlog日志歼郭。
3.3.4 隔離性的實(shí)現(xiàn)
innodb隔離性有四種遗契,我們簡(jiǎn)單看一下四種隔離級(jí)別都是怎么實(shí)現(xiàn)的。下一篇文章中會(huì)詳細(xì)介紹病曾。
1姊途、讀未提交:沒(méi)做任何控制。能夠讀到一個(gè)事務(wù)中的中間狀態(tài)知态,是違背ACID的捷兰,所以在MySQL中基本不用。
2负敏、讀已提交(RC):通過(guò)對(duì)數(shù)據(jù)加了寫(xiě)鎖贡茅,在寫(xiě)的過(guò)程中數(shù)據(jù)是不能被其他事務(wù)看到的。但是會(huì)存在不可重復(fù)讀的問(wèn)題。
3顶考、可重復(fù)讀(RR):通過(guò)增加間隙鎖赁还,解決了不可重讀的問(wèn)題,但是并不能對(duì)未存在的數(shù)據(jù)進(jìn)行加鎖操作驹沿,所以會(huì)存在幻讀的問(wèn)題艘策。
4、可串行化:通過(guò)加鎖渊季,所有的操作都是單版本朋蔫,串行化的。
3.3.5 一致性的實(shí)現(xiàn)
一致性可以歸納為完整性却汉。而數(shù)據(jù)的完整性是通過(guò)上面三個(gè)特性來(lái)保證的驯妄,包括原子性、隔離性合砂、持久性青扔,而這三個(gè)特性又是通過(guò)Redo/Undo/binlog 來(lái)保證的。
4 總結(jié)
本文根據(jù)我自己的學(xué)習(xí)過(guò)程翩伪,簡(jiǎn)單整理了事務(wù)微猖,事務(wù)特性,以及事務(wù)特性背后的技術(shù)原理缘屹。
5 參考文獻(xiàn)
淺入淺出mysql https://draveness.me/mysql-innodb
淺入深出MySQL中事務(wù)的實(shí)現(xiàn) https://draveness.me/mysql-transaction
詳細(xì)分析MySQL事務(wù)日志(redo log和undo log) https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html#auto_id_16
拉勾網(wǎng)的《高性能mysql實(shí)戰(zhàn)》課程 https://kaiwu.lagou.com/course/courseInfo.htm?courseId=5#/content?courseId=5
6 其他
本文是mysql學(xué)習(xí)的第一篇-事務(wù)及其特性凛剥,希望對(duì)你有所幫助~
如果有疑問(wèn),可以直接留言囊颅,也可以關(guān)注公眾號(hào) “鏈人成長(zhǎng)chainerup” 提問(wèn)留言当悔,或者加入知識(shí)星球“鏈人成長(zhǎng)” 與我深度鏈接~