前置文章:
一险毁、MySQL-存儲(chǔ)引擎
零疙教、本文綱要
- 一容贝、事務(wù)
- 二、MySQL事務(wù)原理
- 三楼眷、redo log(重做日志)
- 四铲汪、undo log(回滾日志)
- 五熊尉、MVCC
1焚挠、當(dāng)前讀
2麸俘、快照讀
3、MVCC實(shí)現(xiàn)
4轻纪、MVCC原理分析
tips:Ctrl + F快速定位所需內(nèi)容閱讀吧齿梁。
一催植、事務(wù)
1、事務(wù)介紹
事務(wù)是一組操作的集合士飒,它是一個(gè)不可分割的工作單位查邢,事務(wù)會(huì)把所有的操作作為一個(gè)整體一起向系統(tǒng)提交或撤銷操作的請(qǐng)求,即這些操作要么同時(shí)成功酵幕,要么同時(shí)失敗扰藕。
2、事務(wù)特性
- 原子性(Atomicity):事務(wù)是不可分割的最小操作單元芳撒,要么全部成功邓深,要么全部失敗笔刹;
- 一致性(Consistency):事務(wù)完成時(shí)芥备,必須使所有的數(shù)據(jù)都保持一致狀態(tài);
- 隔離性(Isolation):數(shù)據(jù)庫系統(tǒng)提供的隔離機(jī)制舌菜,保證事務(wù)在不受外部并發(fā)操作影響的獨(dú)立環(huán)境下運(yùn)行萌壳;
- 持久性(Durability):事務(wù)一旦提交或回滾,它對(duì)數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久的日月。
二袱瓮、MySQL事務(wù)原理
1、redo log & undo log
InnoDB中使用redo log
和undo log
來保證事務(wù)的原子性爱咬、一致性尺借、持久性。
2精拟、鎖 & MVCC
InnoDB中使用鎖
和MVCC
來保證事務(wù)的隔離性燎斩。
三、redo log(重做日志)
1蜂绎、redo log介紹
redo log(重做日志)栅表,記錄的是事務(wù)提交時(shí)數(shù)據(jù)頁的物理修改,是用來實(shí)現(xiàn)事務(wù)的持久性师枣。
2谨读、redo log作用
該日志文件由兩部分組成:重做日志緩沖(redo log buffer
)以及重做日志文件(redo log file
),前者是在內(nèi)存中坛吁,后者在磁盤中劳殖。
當(dāng)事務(wù)提交之后會(huì)把所有修改信息都存到該日志文件中,用于在刷新臟頁到磁盤拨脉,發(fā)生錯(cuò)誤時(shí)哆姻,進(jìn)行數(shù)據(jù)恢復(fù)使用。
3玫膀、對(duì)比redo log有無情形
- 有redo log:
① 當(dāng)對(duì)緩沖區(qū)的數(shù)據(jù)進(jìn)行增刪改之后矛缨,會(huì)首先將操作的數(shù)據(jù)頁的變化,記錄在redo log buffer中帖旨;
② 在事務(wù)提交時(shí)箕昭,會(huì)將redo log buffer中的數(shù)據(jù)刷新到redo log磁盤文件中;
③ 過一段時(shí)間之后解阅,如果刷新緩沖區(qū)的臟頁到磁盤時(shí)落竹,發(fā)生錯(cuò)誤,此時(shí)就可以借助于redo log進(jìn)行數(shù)據(jù)恢復(fù)货抄,這樣就保證了事務(wù)的持久性述召;
④ 而如果臟頁成功刷新到磁盤 或 或者涉及到的數(shù)據(jù)已經(jīng)落盤,此時(shí)redolog就沒有作用了蟹地,就可以刪除了积暖,所以存在的兩個(gè)redolog文件是循環(huán)寫的。
#ib_logfile0
#ib_logfile1
4怪与、WAL
在業(yè)務(wù)操作中夺刑,我們操作數(shù)據(jù)一般都是隨機(jī)讀寫磁盤
的,而不是順序讀寫磁盤分别。 而redo log在往磁盤文件中寫入數(shù)據(jù)遍愿,由于是日志文件,所以都是順序?qū)?/code>的茎杂。順序?qū)懙男蚀砝溃h(yuǎn)大于隨機(jī)寫。這種先寫日志的方式煌往,稱之為 WAL(Write-Ahead Logging)倾哺。
5、刷盤時(shí)機(jī)
innodb_flush_log_at_trx_commit:
0: 每秒將日志寫入并刷新到磁盤一次刽脖;
1: 日志在每次事務(wù)提交時(shí)寫入并刷新到磁盤羞海,默認(rèn)值;
2: 日志在每次事務(wù)提交后寫入曲管,并每秒刷新到磁盤一次却邓。
四、undo log(回滾日志)
1院水、undo log介紹
回滾日志(也稱撤銷日志
)腊徙,用于記錄數(shù)據(jù)被修改前的信息 , 作用包含兩個(gè) : 提供回滾(保證事務(wù)的原子性)
和MVCC(多版本并發(fā)控制)
简十。
undo log記錄的是邏輯日志,可以認(rèn)為記錄的是與我們執(zhí)行的update撬腾、insert螟蝙、delete相反的邏輯語句。
2民傻、undo log銷毀
undo log在事務(wù)執(zhí)行時(shí)產(chǎn)生胰默,事務(wù)提交時(shí),并不會(huì)立即刪除undo log漓踢,因?yàn)檫@些日志可能還用于MVCC牵署。
3、undo log存儲(chǔ)
undo log采用段的方式進(jìn)行管理和記錄喧半,存放在rollback segment回滾段中奴迅,內(nèi)部包含1024個(gè)undo log segment。
五薯酝、MVCC
1半沽、當(dāng)前讀
讀取的是記錄的最新版本,讀取時(shí)還要保證其他并發(fā)事務(wù)不能修改當(dāng)前記錄吴菠,會(huì)對(duì)讀取的記錄進(jìn)行加鎖者填。
- ① 對(duì)應(yīng)SQL
- select ... lock in share mode(共享鎖);
- select ...for update(排它鎖)做葵;
- update占哟、insert、delete(排它鎖)酿矢。
- ② 演示示例
Ⅰ 事務(wù)B提交后榨乎,事務(wù)A當(dāng)前讀,可以讀到最新數(shù)據(jù)瘫筐,如下:
Ⅱ 事務(wù)B提交后蜜暑,事務(wù)A快照讀,不能讀到最新數(shù)據(jù)策肝,如下:
2肛捍、快照讀
簡(jiǎn)單的select(不加鎖)就是快照讀,快照讀之众,讀取的是記錄數(shù)據(jù)的可見版本拙毫,有可能是歷史數(shù)據(jù),不加鎖棺禾,是非阻塞讀缀蹄。
- ① 快照讀的不同情形
- Read Committed:每次select,都生成一個(gè)快照讀;
- Repeatable Read:開啟事務(wù)后第一個(gè)select語句才是快照讀的地方缺前;
- Serializable:快照讀會(huì)退化為當(dāng)前讀蛀醉。
- ② 演示示例
具體示例見上。
3诡延、MVCC實(shí)現(xiàn)
MVCC全稱 Multi-Version Concurrency Control滞欠,多版本并發(fā)控制。指維護(hù)一個(gè)數(shù)據(jù)的多個(gè)版本肆良,使得讀寫操作沒有沖突,快照讀為MySQL實(shí)現(xiàn)MVCC提供了一個(gè)非阻塞讀功能逸绎。MVCC的具體實(shí)現(xiàn)惹恃,還需要依賴于數(shù)據(jù)庫記錄中的三個(gè)隱式字段
、undo log日志
棺牧、readView
巫糙。
- ① 三個(gè)隱式字段
Ⅰ DB_TRX_ID:最近修改事務(wù)ID,記錄插入這條記錄或最后一次修改該記錄的事務(wù)ID颊乘;
Ⅱ DB_ROLL_PTR:回滾指針参淹,指向這條記錄的上一個(gè)版本,用于配合undo log乏悄,指向上一個(gè)版本浙值;
Ⅲ DB_ROW_ID:隱藏主鍵,如果表結(jié)構(gòu)沒有指定主鍵檩小,將會(huì)生成該隱藏字段开呐。
查看.ibd文件存儲(chǔ)位置的命令:show global variables like '%datadir%';
,位置為/var/lib/mysql/
规求,如下:
show global variables like '%datadir%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| datadir | /var/lib/mysql/ |
+---------------+-----------------+
查看表結(jié)構(gòu)信息的指令筐付,如下:
ibd2sdi ***.ibd
演示示例:
-- 創(chuàng)建未設(shè)置主鍵的tb_test02表格
create table tb_test02 (id int , name varchar(10));
-- 查看tb_test02表格的各列信息
[root@localhost test]# ibd2sdi tb_test02.ibd
-- 截取指令輸出的關(guān)鍵內(nèi)容
"columns": [
{
"name": "id",
},
{
"name": "name",
},
{
"name": "DB_ROW_ID",
},
{
"name": "DB_TRX_ID",
},
{
"name": "DB_ROLL_PTR",
}
],
- ② undo log(回滾日志)
回滾日志(又稱撤銷日志),在insert阻肿、update瓦戚、delete的時(shí)候產(chǎn)生的便于數(shù)據(jù)回滾的日志。
Ⅰ 當(dāng)insert
的時(shí)候丛塌,產(chǎn)生的undo log日志只在回滾時(shí)需要较解,在事務(wù)提交后
,可被立即刪除
姨伤;
Ⅱ 而update
哨坪、delete
的時(shí)候,產(chǎn)生的undo log日志不僅在回滾時(shí)需要乍楚,在快照讀時(shí)也需要当编,不會(huì)立即被刪除
。
注意:insert對(duì)快照讀已存在的數(shù)據(jù)不產(chǎn)生影響徒溪,而update和delete可能產(chǎn)生影響忿偷,所以此處會(huì)有區(qū)別金顿。
版本鏈
:不同事務(wù)或相同事務(wù)對(duì)同一條記錄進(jìn)行修改,會(huì)導(dǎo)致該記錄的undolog生成一條記錄版本鏈表鲤桥,鏈表的頭部
是最新
的舊記錄揍拆,鏈表尾部
是最早
的舊記錄。
- ③ readview(讀視圖)
ReadView(讀視圖)是 快照讀 SQL執(zhí)行時(shí)MVCC提取數(shù)據(jù)的依據(jù)茶凳,記錄并維護(hù)系統(tǒng)當(dāng)前活躍的事務(wù)(未提交的)id嫂拴。
四個(gè)核心字段:
Ⅰ m_ids
:當(dāng)前活躍的事務(wù)ID集合;
Ⅱ min_trx_id
:最小活躍事務(wù)ID贮喧;
Ⅲ max_trx_id
:預(yù)分配事務(wù)ID筒狠,當(dāng)前最大事務(wù)ID+1(因?yàn)槭聞?wù)ID是自增的);
Ⅳ creator_trx_id
:ReadView創(chuàng)建者的事務(wù)ID箱沦。
版本鏈數(shù)據(jù)的訪問規(guī)則(trx_id是當(dāng)前undolog版本鏈對(duì)應(yīng)事務(wù)ID):
生成ReadView的時(shí)機(jī):
Ⅰ READ COMMITTED :在事務(wù)中每一次執(zhí)行快照讀時(shí)
生成ReadView辩恼;
Ⅱ REPEATABLE READ:僅在事務(wù)中第一次執(zhí)行快照讀時(shí)
生成ReadView,后續(xù)復(fù)用該ReadView谓形。
4灶伊、MVCC原理分析
- ① RC(READ COMMITTED)隔離級(jí)別
RC隔離級(jí)別下,在事務(wù)中每一次執(zhí)行快照讀時(shí)生成ReadView寒跳。
示例解讀:
此情形中聘萨,當(dāng)我們對(duì)比到版本鏈中trx_id = 2的時(shí)候,滿足條件②冯袍,此時(shí)該版本就是版本鏈中事務(wù)5可以讀取到的數(shù)據(jù)匈挖。
- ② RR(REPEATABLE READ)隔離級(jí)別
RR隔離級(jí)別下,僅在事務(wù)中第一次執(zhí)行快照讀時(shí)生成ReadView康愤,后續(xù)復(fù)用該ReadView儡循。RR 是可重復(fù)讀,在一個(gè)事務(wù)中征冷,執(zhí)行兩次相同的select語句择膝,查詢到的結(jié)果是一樣的。
六检激、結(jié)尾
以上即為事務(wù)和MVCC部分的內(nèi)容了肴捉,感謝閱讀。