淺談MySQL中是如何實(shí)現(xiàn)事務(wù)提交和回滾的
什么是事務(wù)
事務(wù)是由數(shù)據(jù)庫(kù)中一系列的訪問(wèn)和更新組成的邏輯執(zhí)行單元
事務(wù)的邏輯單元中可以是一條SQL語(yǔ)句,也可以是一段SQL邏輯,這段邏輯要么全部執(zhí)行成功,要么全部執(zhí)行失敗
舉個(gè)最常見(jiàn)的例子,你早上出去買早餐,支付寶掃碼付款給早餐老板,這就是一個(gè)簡(jiǎn)單的轉(zhuǎn)賬過(guò)程,會(huì)包含兩步
- 從你的支付寶賬戶扣款10元
- 早餐老板的賬戶增加10元
這兩步其中任何一部出現(xiàn)問(wèn)題,都會(huì)導(dǎo)致整個(gè)賬務(wù)出現(xiàn)問(wèn)題
- 假如你的支付寶賬戶扣款10元失敗,早餐老板的賬戶增加成功,那你就Happy了,相當(dāng)于馬云請(qǐng)你吃早餐了,O(∩_∩)O哈哈~
- 假如你的支付寶賬戶扣款10元成功,早餐老板的賬戶增加失敗,那你就悲劇了,早餐老板不會(huì)放過(guò)你,會(huì)讓你重新付款,相當(dāng)于你請(qǐng)馬云吃早餐了-_-?
事務(wù)就是用來(lái)保證一系列操作的原子性,上述兩步操作,要么全部執(zhí)行成功,要么全部執(zhí)行失敗
數(shù)據(jù)庫(kù)為了保證事務(wù)的原子性和持久性,引入了redo log和undo log
redo log
redo log是重做日志,通常是物理日志,記錄的是物理數(shù)據(jù)頁(yè)的修改,它用來(lái)恢復(fù)提交后的物理數(shù)據(jù)頁(yè)
如上圖所示,redo log分為兩部分:
- 內(nèi)存中的redo log Buffer是日志緩沖區(qū),這部分?jǐn)?shù)據(jù)是容易丟失的
- 磁盤上的redo log file是日志文件,這部分?jǐn)?shù)據(jù)已經(jīng)持久化到磁盤,不容易丟失
SQL操作數(shù)據(jù)庫(kù)之前,會(huì)先記錄重做日志,為了保證效率會(huì)先寫到日志緩沖區(qū)中(redo log Buffer),再通過(guò)緩沖區(qū)寫到磁盤文件中進(jìn)行持久化,既然有緩沖區(qū)說(shuō)明數(shù)據(jù)不是實(shí)時(shí)寫到redo log file中的,那么假如redo log寫到緩沖區(qū)后,此時(shí)服務(wù)器斷電了,那redo log豈不是會(huì)丟失?
在MySQL中可以自已控制log buffer刷新到log file中的頻率,通過(guò)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ì)通過(guò)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是回滾日志,用來(lái)回滾行記錄到某個(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中,再通過(guò)調(diào)用fsync()方法將日志記錄到log file中
undo log記錄的是邏輯日志,可以簡(jiǎn)單的理解為:當(dāng)insert一條記錄時(shí),undo log會(huì)記錄一條對(duì)應(yīng)的delete語(yǔ)句;當(dāng)update一條語(yǔ)句時(shí),undo log記錄的是一條與之操作相反的語(yǔ)句
當(dāng)事務(wù)需要回滾時(shí),可以從undo log中找到相應(yīng)的內(nèi)容進(jìn)行回滾操作,回滾后數(shù)據(jù)恢復(fù)到操作之前的狀態(tài)
undo日志還有一個(gè)用途就是用來(lái)控制數(shù)據(jù)的多版本(MVCC),在《InnoDB存儲(chǔ)引擎中的鎖》一文中講到MVCC是通過(guò)讀取undo日志中數(shù)據(jù)的快照來(lái)進(jìn)行多版本控制的
undo log是采用段(segment)的方式來(lái)記錄的,每個(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ù)庫(kù)在執(zhí)行SQL操作數(shù)據(jù)之前會(huì)先記錄redo log和undo log
- redo log是重做日志,通常是物理日志,記錄的是物理數(shù)據(jù)頁(yè)的修改,它用來(lái)恢復(fù)提交后的物理數(shù)據(jù)頁(yè)
- undo log是回滾日志,用來(lái)回滾行記錄到某個(gè)版本,undo log一般是邏輯日志,根據(jù)行的數(shù)據(jù)變化進(jìn)行記錄
- redo/undo log都是寫先寫到日志緩沖區(qū),再通過(guò)緩沖區(qū)寫到磁盤日志文件中進(jìn)行持久化保存
- undo日志還有一個(gè)用途就是用來(lái)控制數(shù)據(jù)的多版本(MVCC)
簡(jiǎn)單理解就是:
- redo log是用來(lái)恢復(fù)數(shù)據(jù)的,用于保障已提交事務(wù)的持久性
- undo log是用來(lái)回滾事務(wù)的,用于保障未提交事務(wù)的原子性
到此這篇關(guān)于淺談MySQL中是如何實(shí)現(xiàn)事務(wù)提交和回滾的的文章就介紹到這了,更多相關(guān)MySQL 事務(wù)提交和回滾內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring MVC項(xiàng)目開(kāi)發(fā)踩過(guò)的一些bug
這篇文章主要給大家介紹了關(guān)于Spring MVC項(xiàng)目開(kāi)發(fā)踩過(guò)的一些bug,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11使用IDEA創(chuàng)建Java Web項(xiàng)目并部署訪問(wèn)的圖文教程
本文通過(guò)圖文并茂的形式給大家介紹了使用IDEA創(chuàng)建Java Web項(xiàng)目并部署訪問(wèn)的教程,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-08-08Maven?Pom?文件中的隱式依賴導(dǎo)致Jar沖突問(wèn)題
這篇文章主要介紹了Maven?Pom?文件中的隱式依賴導(dǎo)致Jar沖突問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java實(shí)現(xiàn)兩人五子棋游戲(三) 畫出棋子
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)兩人五子棋游戲,畫出五子棋的棋子,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03使用logstash同步mysql數(shù)據(jù)到elasticsearch實(shí)現(xiàn)
這篇文章主要為大家介紹了使用logstash同步mysql數(shù)據(jù)到elasticsearch實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Java替換中使用正則表達(dá)式實(shí)現(xiàn)中間模糊匹配的方法
今天小編就為大家分享一篇Java替換中使用正則表達(dá)式實(shí)現(xiàn)中間模糊匹配的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07idea快捷鍵生成getter和setter,有構(gòu)造參數(shù),無(wú)構(gòu)造參數(shù),重寫toString方式
這篇文章主要介紹了java之idea快捷鍵生成getter和setter,有構(gòu)造參數(shù),無(wú)構(gòu)造參數(shù),重寫toString方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11簡(jiǎn)單介紹Java?方法的重載、可變參數(shù)、作用域
這篇文章主要簡(jiǎn)單介紹Java?方法的重載、可變參數(shù)、作用域的相關(guān)資料,需要的朋友可以參考下2023-07-07java Collection 之Set使用說(shuō)明
本篇文章小編為大家介紹,java Collection 之Set使用說(shuō)明。需要的朋友參考下2013-04-04Java關(guān)鍵字instanceof用法及實(shí)現(xiàn)策略
instanceof 運(yùn)算符是用來(lái)在運(yùn)行時(shí)判斷對(duì)象是否是指定類及其父類的一個(gè)實(shí)例。這篇文章主要介紹了Java關(guān)鍵字instanceof用法解析,需要的朋友可以參考下2020-08-08