淺談MySQL中是如何實(shí)現(xiàn)事務(wù)提交和回滾的
什么是事務(wù)
事務(wù)是由數(shù)據(jù)庫中一系列的訪問和更新組成的邏輯執(zhí)行單元
事務(wù)的邏輯單元中可以是一條SQL語句,也可以是一段SQL邏輯,這段邏輯要么全部執(zhí)行成功,要么全部執(zhí)行失敗
舉個(gè)最常見的例子,你早上出去買早餐,支付寶掃碼付款給早餐老板,這就是一個(gè)簡單的轉(zhuǎn)賬過程,會(huì)包含兩步
- 從你的支付寶賬戶扣款10元
- 早餐老板的賬戶增加10元
這兩步其中任何一部出現(xiàn)問題,都會(huì)導(dǎo)致整個(gè)賬務(wù)出現(xiàn)問題
- 假如你的支付寶賬戶扣款10元失敗,早餐老板的賬戶增加成功,那你就Happy了,相當(dāng)于馬云請(qǐng)你吃早餐了,O(∩_∩)O哈哈~
- 假如你的支付寶賬戶扣款10元成功,早餐老板的賬戶增加失敗,那你就悲劇了,早餐老板不會(huì)放過你,會(huì)讓你重新付款,相當(dāng)于你請(qǐng)馬云吃早餐了-_-?
事務(wù)就是用來保證一系列操作的原子性,上述兩步操作,要么全部執(zhí)行成功,要么全部執(zhí)行失敗
數(shù)據(jù)庫為了保證事務(wù)的原子性和持久性,引入了redo log和undo log
redo log
redo log是重做日志,通常是物理日志,記錄的是物理數(shù)據(jù)頁的修改,它用來恢復(fù)提交后的物理數(shù)據(jù)頁

如上圖所示,redo log分為兩部分:
- 內(nèi)存中的redo log Buffer是日志緩沖區(qū),這部分?jǐn)?shù)據(jù)是容易丟失的
- 磁盤上的redo log file是日志文件,這部分?jǐn)?shù)據(jù)已經(jīng)持久化到磁盤,不容易丟失
SQL操作數(shù)據(jù)庫之前,會(huì)先記錄重做日志,為了保證效率會(huì)先寫到日志緩沖區(qū)中(redo log Buffer),再通過緩沖區(qū)寫到磁盤文件中進(jìn)行持久化,既然有緩沖區(qū)說明數(shù)據(jù)不是實(shí)時(shí)寫到redo log file中的,那么假如redo log寫到緩沖區(qū)后,此時(shí)服務(wù)器斷電了,那redo log豈不是會(huì)丟失?
在MySQL中可以自已控制log buffer刷新到log file中的頻率,通過innodb_flush_log_at_trx_commit參數(shù)可以設(shè)置事務(wù)提交時(shí)log buffer如何保存到log file中,innodb_flush_log_at_trx_commit參數(shù)有3個(gè)值(0、1、2),表示三種不同的方式
- 為1表示事務(wù)每次提交都會(huì)將log buffer寫入到os buffer,并調(diào)用操作系統(tǒng)的fsync()方法將日志寫入log file,這種方式的好處是就算MySQL崩潰也不會(huì)丟數(shù)據(jù),redo log file保存了所有已提交事務(wù)的日志,MySQL重新啟動(dòng)后會(huì)通過redo log file進(jìn)行恢復(fù)。但這種方式每次提交事務(wù)都會(huì)寫入磁盤,IO性能較差
- 為0表示事務(wù)提交時(shí)不會(huì)將log buffer寫入到os buffer中,而是每秒寫入os buffer然后調(diào)用fsync()方法將日志寫入log file,這種方式在MySQL系統(tǒng)崩潰時(shí)會(huì)丟失大約1秒鐘的數(shù)據(jù)
- 為2表示事務(wù)每次提交僅將log buffer寫入到os buffer中,然后每秒調(diào)用fsync()方法將日志寫入log file,這種方式在MySQL崩潰時(shí)也會(huì)丟失大約1秒鐘的數(shù)據(jù)
undo log
undo log是回滾日志,用來回滾行記錄到某個(gè)版本,undo log一般是邏輯日志,根據(jù)行的數(shù)據(jù)變化進(jìn)行記錄
undo log跟redo log一樣也是在SQL操作數(shù)據(jù)之前記錄的,也就是SQL操作先記錄日志,再進(jìn)行操作數(shù)據(jù)

如上圖所示,SQL操作之前會(huì)先記錄redo log、undo log到日志緩沖區(qū),日志緩沖區(qū)的數(shù)據(jù)會(huì)記錄到os buffer中,再通過調(diào)用fsync()方法將日志記錄到log file中
undo log記錄的是邏輯日志,可以簡單的理解為:當(dāng)insert一條記錄時(shí),undo log會(huì)記錄一條對(duì)應(yīng)的delete語句;當(dāng)update一條語句時(shí),undo log記錄的是一條與之操作相反的語句
當(dāng)事務(wù)需要回滾時(shí),可以從undo log中找到相應(yīng)的內(nèi)容進(jìn)行回滾操作,回滾后數(shù)據(jù)恢復(fù)到操作之前的狀態(tài)
undo日志還有一個(gè)用途就是用來控制數(shù)據(jù)的多版本(MVCC),在《InnoDB存儲(chǔ)引擎中的鎖》一文中講到MVCC是通過讀取undo日志中數(shù)據(jù)的快照來進(jìn)行多版本控制的
undo log是采用段(segment)的方式來記錄的,每個(gè)undo操作在記錄的時(shí)候占用一個(gè)undo log segment。
另外,undo log也會(huì)產(chǎn)生redo log,因?yàn)閡ndo log也要實(shí)現(xiàn)持久性保護(hù)
總結(jié)一下
MySQL中是如何實(shí)現(xiàn)事務(wù)提交和回滾的?
- 為了保證數(shù)據(jù)的持久性,數(shù)據(jù)庫在執(zhí)行SQL操作數(shù)據(jù)之前會(huì)先記錄redo log和undo log
- redo log是重做日志,通常是物理日志,記錄的是物理數(shù)據(jù)頁的修改,它用來恢復(fù)提交后的物理數(shù)據(jù)頁
- undo log是回滾日志,用來回滾行記錄到某個(gè)版本,undo log一般是邏輯日志,根據(jù)行的數(shù)據(jù)變化進(jìn)行記錄
- redo/undo log都是寫先寫到日志緩沖區(qū),再通過緩沖區(qū)寫到磁盤日志文件中進(jìn)行持久化保存
- undo日志還有一個(gè)用途就是用來控制數(shù)據(jù)的多版本(MVCC)
簡單理解就是:
- redo log是用來恢復(fù)數(shù)據(jù)的,用于保障已提交事務(wù)的持久性
- undo log是用來回滾事務(wù)的,用于保障未提交事務(wù)的原子性
到此這篇關(guān)于淺談MySQL中是如何實(shí)現(xiàn)事務(wù)提交和回滾的的文章就介紹到這了,更多相關(guān)MySQL 事務(wù)提交和回滾內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于獲取JAVA路徑,包括CLASSPATH外的路徑的方法詳解
本篇文章是對(duì)獲取JAVA路徑,包括CLASSPATH外的路徑的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
解決springboot自定義配置Boolean屬性不能生效的問題
這篇文章主要介紹了解決springboot自定義配置Boolean屬性不能生效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
dubbo擴(kuò)展點(diǎn)AOP切面功能擴(kuò)展示例詳解
這篇文章主要為大家介紹了dubbo擴(kuò)展點(diǎn)AOP切面功能擴(kuò)展示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
JAVA 并發(fā)容器的一些易出錯(cuò)點(diǎn)你知道嗎
今天給大家?guī)淼奈恼率荍ava并發(fā)編程的相關(guān)知識(shí),文中對(duì)java同步容器與并發(fā)容器做了非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-09-09
SpringBoot+Websocket實(shí)現(xiàn)一個(gè)簡單的網(wǎng)頁聊天功能代碼
本篇文章主要介紹了SpringBoot+Websocket實(shí)現(xiàn)一個(gè)簡單的網(wǎng)頁聊天功能代碼,具有一定的參考價(jià)值,有需要的可以了解一下2017-08-08
解決spring cloud服務(wù)啟動(dòng)之后回到命令行會(huì)自動(dòng)掛掉問題
這篇文章主要介紹了解決spring cloud服務(wù)啟動(dòng)之后回到命令行會(huì)自動(dòng)掛掉問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Java 時(shí)間轉(zhuǎn)換的實(shí)例代碼
下面小編就為大家?guī)硪黄狫ava 時(shí)間轉(zhuǎn)換的實(shí)例代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07
javaweb實(shí)戰(zhàn)之商城項(xiàng)目開發(fā)(三)
這篇文章主要針對(duì)javaweb商城項(xiàng)目開發(fā)進(jìn)行實(shí)戰(zhàn)演習(xí),主要實(shí)現(xiàn)通用的BaseDao.java和使用resultMap映射關(guān)聯(lián)對(duì)象,感興趣的小伙伴們可以參考一下2016-02-02

