熬夜肝出5大總結债沮,16個技術點帶你徹底弄懂MySQL事務日志

在當今社會,充斥著大量的數據味滞。從眾多APP上的賬戶資料到銀行信用體系等個人檔案,都離不開對大量數據的組織、存儲和管理剑鞍。而這昨凡,便是數據庫存在的目的和價值。目前數據庫的類型主要分為兩種蚁署,一種是關系型數據庫便脊,另一種是非關系型數據庫(NoSQL)。而我們今天的主角MySQL就是關系型數據庫中的一種形用。

一就轧、關系型數據庫與NoSQL

關系型數據庫,顧名思義田度,是指存儲的數據之間具有關系。這種所謂的關系通常用二維表格中的行列來表示解愤,即一個二維表的邏輯結構能夠反映表中數據的存儲關系镇饺。

概念總是拗口難懂的。那么簡單來說送讲,關系型數據庫的存儲就是按照表格進行的奸笤。數據的存儲實際上就是對一個或者多個表格的存儲。通過對這些表格進行分類哼鬓、合并监右、連接或者選取等運算來實現對數據庫的管理。常見的關系型數據庫有MySQL异希、Oracle健盒、DB2和SqlServer等。

非關系型數據庫(NoSQL)是相對于關系型數據庫的一種泛指称簿,它的特點是去掉了關系型數據庫中的關系特性扣癣,從而可獲得更好的擴展性。NoSQL并沒有嚴格的存儲方式憨降,但采用不同的存儲結構都是為了獲得更高的性能和更高的并發(fā)父虑。

NoSQL根據存儲方式可分為四大類,鍵值存儲數據庫授药、列存儲數據庫士嚎、文檔型數據庫和圖形數據庫。這四種數據的存儲原理不盡相同悔叽,因而在應用場景上也有些許的差異莱衩。一般常用的有作為數據緩存的redis和分布式系統的HBase。目前常見的數據庫排名可見網站:

https://db-engines.com/en/ranking

關系型數據庫與非關系型數據庫本質上的區(qū)別就在于存儲的數據是否具有一定的邏輯關系骄蝇,由此產生的兩類數據庫看的性能和優(yōu)劣勢上也有一定的區(qū)別膳殷。二者對比可見下圖。

二、MySQL簡介

介紹

在關系型數據庫中赚窃,MySQL可以說是其中的王者册招。它是目前最流行的數據庫之一,由瑞典 MySQL AB 公司開發(fā)勒极,目前屬于 Oracle 公司是掰。MySQL數據庫具有以下幾個方面的優(yōu)勢:

  • 體積小、速度快辱匿;
  • 代碼開源键痛,采用了 GPL 協議,可以修改源碼來開發(fā)自己的 MySQL 系統匾七;
  • 支持大型的數據庫絮短,可以處理擁有上千萬條記錄的大型數據庫;
  • 使用標準的 SQL 數據語言形式昨忆,并采用優(yōu)化的 SQL 查詢算法丁频,有效地提高查詢速度;
  • 使用 C 和 C++ 編寫邑贴,并使用多種編譯器進行測試席里,保證源代碼的可移植性;
  • 可運行在多個系統上拢驾,并且支持多種語言奖磁;
  • 核心程序采用完全的多線程編程,可以靈活地為用戶提供服務繁疤,充分利用CPU資源咖为。

邏輯架構

MySQL的邏輯架構可分為四層,包括連接層嵌洼、服務層案疲、引擎層和存儲層,各層的接口交互及作用如下圖所示麻养。需要注意的是褐啡,由于本文將主要講解事務的實現原理,因此下文針對的都是InnoDB引擎下的情況鳖昌。

連接層: 負責處理客戶端的連接以及權限的認證备畦。

服務層: 定義有許多不同的模塊,包括權限判斷许昨,SQL接口懂盐,SQL解析,SQL分析優(yōu)化糕档, 緩存查詢的處理以及部分內置函數執(zhí)行等莉恼。MySQL的查詢語句在服務層內進行解析、優(yōu)化、緩存以及內置函數的實現和存儲俐银。

引擎層: 負責MySQL中數據的存儲和提取尿背。MySQL中的服務器層不管理事務,事務是由存儲引擎實現的捶惜。其中使用最為廣泛的存儲引擎為InnoDB田藐,其它的引擎都不支持事務。

存儲層: 負責將數據存儲與設備的文件系統中吱七。

三汽久、MySQL事務

事務是MySQL區(qū)別于NoSQL的重要特征,是保證關系型數據庫數據一致性的關鍵技術踊餐。事務可看作是對數據庫操作的基本執(zhí)行單元景醇,可能包含一個或者多個SQL語句。這些語句在執(zhí)行時市袖,要么都執(zhí)行啡直,要么都不執(zhí)行。事務的執(zhí)行主要包括兩個操作苍碟,提交和回滾。

提交:commit撮执,將事務執(zhí)行結果寫入數據庫微峰。

回滾:rollback,回滾所有已經執(zhí)行的語句抒钱,返回修改之前的數據蜓肆。

MySQL事務包含四個特性,號稱ACID四大天王谋币。

原子性(Atomicity) :語句要么全執(zhí)行仗扬,要么全不執(zhí)行,是事務最核心的特性蕾额,事務本身就是以原子性來定義的早芭;實現主要基于undo log日志實現的。
持久性(Durability :保證事務提交后不會因為宕機等原因導致數據丟失诅蝶;實現主要基于redo log日志退个。
隔離性(Isolation) :保證事務執(zhí)行盡可能不受其他事務影響;InnoDB默認的隔離級別是RR调炬,RR的實現主要基于鎖機制语盈、數據的隱藏列、undo log和類next-key lock機制缰泡。
一致性(Consistency) :事務追求的最終目標刀荒,一致性的實現既需要數據庫層面的保障,也需要應用層面的保障。

原子性

事務的原子性就如原子操作一般缠借,表示事務不可再分干毅,其中的操作要么都做,要么都不做烈炭;如果事務中一個SQL語句執(zhí)行失敗溶锭,則已執(zhí)行的語句也必須回滾,數據庫退回到事務前的狀態(tài)符隙。只有0和1趴捅,沒有其它值。

事務的原子性表明事務就是一個整體霹疫,當事務無法成功執(zhí)行的時候拱绑,需要將事務中已經執(zhí)行過的語句全部回滾,使得數據庫回歸到最初未開始事務的狀態(tài)丽蝎。

事務的原子性就是通過undo log日志進行實現的猎拨。當事務需要進行回滾時,InnoDB引擎就會調用undo log日志進行SQL語句的撤銷屠阻,實現數據的回滾红省。

持久性

事務的持久性是指當事務提交之后,數據庫的改變就應該是永久性的国觉,而不是暫時的吧恃。這也就是說,當事務提交之后麻诀,任何其它操作甚至是系統的宕機故障都不會對原來事務的執(zhí)行結果產生影響痕寓。

事務的持久性是通過InnoDB存儲引擎中的redo log日志來實現的,具體實現思路見下文蝇闭。

隔離性

原子性和持久性是單個事務本身層面的性質呻率,而隔離性是指事務之間應該保持的關系。隔離性要求不同事務之間的影響是互不干擾的呻引,一個事務的操作與其它事務是相互隔離的礼仗。

由于事務可能并不只包含一條SQL語句,所以在事務的執(zhí)行期間很有可能會有其它事務開始執(zhí)行苞七。因此多事務的并發(fā)性就要求事務之間的操作是相互隔離的藐守。這一點跟多線程之間數據同步的概念有些類似。

鎖機制

事務之間的隔離蹂风,是通過鎖機制實現的卢厂。當一個事務需要對數據庫中的某行數據進行修改時,需要先給數據加鎖惠啄;加了鎖的數據慎恒,其它事務是不運行操作的任内,只能等待當前事務提交或回滾將鎖釋放。

鎖機制并不是一個陌生的概念融柬,在許多場景中都會利用到不同實現的鎖對數據進行保護和同步死嗦。而在MySQL中,根據不同的劃分標準粒氧,還可將鎖分為不同的種類越除。

按照粒度劃分:行鎖、表鎖外盯、頁鎖
按照使用方式劃分:共享鎖摘盆、排它鎖
按照思想劃分:悲觀鎖、樂觀鎖

鎖機制的知識點很多饱苟,由于篇幅不好全部展開講孩擂。這里對按照粒度劃分的鎖進行簡單介紹。

粒度:指數據倉庫的數據單位中保存數據的細化或綜合程度的級別箱熬。細化程度越高类垦,粒度級就越小城须;相反蚤认,細化程度越低,粒度級就越大糕伐。

MySQL按照鎖的粒度劃分可以分為行鎖烙懦、表鎖和頁鎖。

行鎖:粒度最小的鎖赤炒,表示只針對當前操作的行進行加鎖;

表鎖:粒度最大的鎖亏较,表示當前的操作對整張表加鎖莺褒;

頁鎖:粒度介于行級鎖和表級鎖中間的一種鎖,表示對頁進行加鎖雪情。

這三種鎖是在不同層次上對數據進行鎖定遵岩,由于粒度的不同,其帶來的好處和劣勢也不一而同巡通。

表鎖在操作數據時會鎖定整張表尘执,因而并發(fā)性能較差;

行鎖則只鎖定需要操作的數據宴凉,并發(fā)性能好誊锭。但是由于加鎖本身需要消耗資源(獲得鎖、檢查鎖弥锄、釋放鎖等都需要消耗資源)丧靡,因此在鎖定數據較多情況下使用表鎖可以節(jié)省大量資源蟆沫。

MySQL中不同的存儲引擎能夠支持的鎖也是不一樣的。MyIsam只支持表鎖温治,而InnoDB同時支持表鎖和行鎖饭庞,且出于性能考慮,絕大多數情況下使用的都是行鎖熬荆。

并發(fā)讀寫問題

在并發(fā)情況下舟山,MySQL的同時讀寫可能會導致三類問題,臟讀卤恳、不可重復度和幻讀累盗。

(1)臟讀:當前事務中讀到其他事務未提交的數據,也就是臟數據纬黎。

以上圖為例幅骄,事務A在讀取文章的閱讀量時,讀取到了事務B為提交的數據本今。如果事務B最后沒有順利提交拆座,導致事務回滾,那么實際上閱讀量并沒有修改成功冠息,而事務A卻是讀到的修改后的值挪凑,顯然不合情理。

(2)不可重復讀:在事務A中先后兩次讀取同一個數據逛艰,但是兩次讀取的結果不一樣躏碳。臟讀與不可重復讀的區(qū)別在于:前者讀到的是其他事務未提交的數據,后者讀到的是其他事務已提交的數據散怖。

以上圖為例菇绵,事務A在先后讀取文章閱讀量的數據時,結果卻不一樣镇眷。說明事務A在執(zhí)行的過程中咬最,閱讀量的值被其它事務給修改了。這樣使得數據的查詢結果不再可靠欠动,同樣也不合實際永乌。

(3)幻讀:在事務A中按照某個條件先后兩次查詢數據庫,兩次查詢結果的行數不同具伍,這種現象稱為幻讀翅雏。不可重復讀與幻讀的區(qū)別可以通俗的理解為:前者是數據變了,后者是數據的行數變了人芽。

以上圖為例望几,當對0<閱讀量<100的文章進行查詢時,先查到了一個結果啼肩,后來查詢到了兩個結果橄妆。這表明同一個事務的查詢結果數不一衙伶,行數不一致。這樣的問題使得在根據某些條件對數據篩選的時候害碾,前后篩選結果不具有可靠性矢劲。

隔離級別

根據上面這三種問題,產生了四種隔離級別慌随,表明數據庫不同程度的隔離性質芬沉。

在實際的數據庫設計中,隔離級別越高阁猜,導致數據庫的并發(fā)效率會越低丸逸;而隔離級別太低,又會導致數據庫在讀寫過程中會遇到各種亂七八糟的問題剃袍。

因此在大多數數據庫系統中黄刚,默認的隔離級別時讀已提交(如Oracle)或者可重復讀RR(MySQL的InnoDB引擎)。

MVCC

又是一個難嚼的大塊頭民效。MVCC就是用來實現上面的第三個隔離級別憔维,可重復讀RR。

MVCC:Multi-Version Concurrency Control畏邢,即多版本的并發(fā)控制協議业扒。

MVCC的特點就是在同一時刻,不同事務可以讀取到不同版本的數據舒萎,從而可以解決臟讀和不可重復讀的問題程储。

MVCC實際上就是通過數據的隱藏列和回滾日志(undo log),實現多個版本數據的共存臂寝。這樣的好處是章鲤,使用MVCC進行讀數據的時候,不用加鎖咆贬,從而避免了同時讀寫的沖突咏窿。

在實現MVCC時,每一行的數據中會額外保存幾個隱藏的列素征,比如當前行創(chuàng)建時的版本號和刪除時間和指向undo log的回滾指針。這里的版本號并不是實際的時間值萝挤,而是系統版本號御毅。每開始新的事務,系統版本號都會自動遞增怜珍。事務開始時的系統版本號會作為事務的版本號端蛆,用來和查詢每行記錄的版本號進行比較。

每個事務又有自己的版本號酥泛,這樣事務內執(zhí)行數據操作時今豆,就通過版本號的比較來達到數據版本控制的目的嫌拣。

另外,InnoDB實現的隔離級別RR時可以避免幻讀現象的呆躲,這是通過next-key lock機制實現的异逐。

next-key lock實際上就是行鎖的一種,只不過它不只是會鎖住當前行記錄的本身插掂,還會鎖定一個范圍灰瞻。比如上面幻讀的例子,開始查詢0<閱讀量<100的文章時辅甥,只查到了一個結果酝润。next-key lock會將查詢出的這一行進行鎖定,同時還會對0<閱讀量<100這個范圍進行加鎖璃弄,這實際上是一種間隙鎖要销。間隙鎖能夠防止其他事務在這個間隙修改或者插入記錄。這樣一來夏块,就保證了在0<閱讀量<100這個間隙中疏咐,只存在原來的一行數據,從而避免了幻讀拨扶。

間隙鎖:封鎖索引記錄中的間隔

雖然InnoDB使用next-key lock能夠避免幻讀問題凳鬓,但卻并不是真正的可串行化隔離。再來看一個例子吧患民。

首先提一個問題:

在T6時間缩举,事務A提交事務之后,猜一猜文章A和文章B的閱讀量為多少匹颤?

答案是仅孩,文章AB的閱讀量都被修改成了10000。這代表著事務B的提交實際上對事務A的執(zhí)行產生了影響印蓖,表明兩個事務之間并不是完全隔離的辽慕。雖然能夠避免幻讀現象,但是卻沒有達到可串行化的級別赦肃。

這還說明溅蛉,避免臟讀、不可重復讀和幻讀他宛,是達到可串行化的隔離級別的必要不充分條件船侧。可串行化是都能夠避免臟讀厅各、不可重復讀和幻讀镜撩,但是避免臟讀、不可重復讀和幻讀卻不一定達到了可串行化队塘。

一致性

一致性是指事務執(zhí)行結束后袁梗,數據庫的完整性約束沒有被破壞宜鸯,事務執(zhí)行的前后都是合法的數據狀態(tài)。一致性是事務追求的最終目標遮怜,原子性淋袖、持久性和隔離性,實際上都是為了保證數據庫狀態(tài)的一致性而存在的奈泪。這就不多說了吧适贸。你細品。

四涝桅、MySQL日志系統

了解完MySQL的基本架構拜姿,大體上能夠對MySQL的執(zhí)行流程有了比較清晰的認知。接下來我將為大家介紹一下日志系統冯遂。

MySQL日志系統是數據庫的重要組件蕊肥,用于記錄數據庫的更新和修改。若數據庫發(fā)生故障蛤肌,可通過不同日志記錄恢復數據庫的原來數據壁却。因此實際上日志系統直接決定著MySQL運行的魯棒性和穩(wěn)健性。

MySQL的日志有很多種裸准,如二進制日志(binlog)展东、錯誤日志、查詢日志炒俱、慢查詢日志等盐肃,此外InnoDB存儲引擎還提供了兩種日志:redo log(重做日志)和undo log(回滾日志)。這里將重點針對InnoDB引擎权悟,對重做日志砸王、回滾日志和二進制日志這三種進行分析。

重做日志(redo log)

重做日志(redo log)是InnoDB引擎層的日志峦阁,用來記錄事務操作引起數據的變化谦铃,記錄的是數據頁的物理修改。

重做日記的作用其實很好理解榔昔,我打個比方驹闰。數據庫中數據的修改就好比你寫的論文,萬一哪天論文丟了怎么呢撒会?以防這種不幸的發(fā)生疮方,我們可以在寫論文的時候,每一次修改都拿個小本本記錄一下茧彤,記錄什么時間對某一頁進行了怎么樣的修改。這就是重做日志疆栏。

InnoDB引擎對數據的更新曾掂,是先將更新記錄寫入redo log日志惫谤,然后會在系統空閑的時候或者是按照設定的更新策略再將日志中的內容更新到磁盤之中。這就是所謂的預寫式技術(Write Ahead logging)珠洗。這種技術可以大大減少IO操作的頻率溜歪,提升數據刷新的效率。

臟數據刷盤

值得注意的是许蓖,redo log日志的大小是固定的蝴猪,為了能夠持續(xù)不斷的對更新記錄進行寫入,在redo log日志中設置了兩個標志位置膊爪,checkpoint和write_pos自阱,分別表示記錄擦除的位置和記錄寫入的位置。redo log日志的數據寫入示意圖可見下圖米酬。

write_pos標志到了日志結尾時沛豌,會從結尾跳至日志頭部進行重新循環(huán)寫入。所以redo log的邏輯結構并不是線性的赃额,而是可看作一個圓周運動加派。write_poscheckpoint中間的空間可用于寫入新數據,寫入和擦除都是往后推移跳芳,循環(huán)往復的芍锦。

write_pos追上checkpoint時,表示redo log日志已經寫滿飞盆。這時不能繼續(xù)執(zhí)行新的數據庫更新語句娄琉,需要停下來先刪除一些記錄,執(zhí)行checkpoint規(guī)則騰出可寫空間桨啃。

checkpoint規(guī)則:checkpoint觸發(fā)后车胡,將buffer中臟數據頁和臟日志頁都刷到磁盤。

臟數據:指內存中未刷到磁盤的數據照瘾。

redo log中最重要的概念就是緩沖池buffer pool匈棘,這是在內存中分配的一個區(qū)域,包含了磁盤中部分數據頁的映射析命,作為訪問數據庫的緩沖主卫。

當請求讀取數據時,會先判斷是否在緩沖池命中鹃愤,如果未命中才會在磁盤上進行檢索后放入緩沖池芒涡;

當請求寫入數據時,會先寫入緩沖池栏渺,緩沖池中修改的數據會定期刷新到磁盤中怔接。這一過程也被稱之為刷臟

因此,當數據修改時姿现,除了修改buffer pool中的數據肠仪,還會在redo log中記錄這次操作;當事務提交時备典,會根據redo log的記錄對數據進行刷盤异旧。如果MySQL宕機,重啟時可以讀取redo log中的數據提佣,對數據庫進行恢復吮蛹,從而保證了事務的持久性,使得數據庫獲得crash-safe能力拌屏。

臟日志刷盤

除了上面提到的對于臟數據的刷盤潮针,實際上redo log日志在記錄時,為了保證日志文件的持久化槐壳,也需要經歷將日志記錄從內存寫入到磁盤的過程然低。redo log日志可分為兩個部分,一是存在易失性內存中的緩存日志redo log buff务唐,二是保存在磁盤上的redo log日志文件redo log file雳攘。

為了確保每次記錄都能夠寫入到磁盤中的日志中,每次將redo log buffer中的日志寫入redo log file的過程中都會調用一次操作系統的fsync操作枫笛。

fsync函數:包含在UNIX系統頭文件#include <unistd.h>中吨灭,用于同步內存中所有已修改的文件數據到儲存設備。

在寫入的過程中刑巧,還需要經過操作系統內核空間的os buffer喧兄。redo log日志的寫入過程可見下圖。

二進制日志(binlog)

二進制日志binlog是服務層的日志啊楚,還被稱為歸檔日志吠冤。binlog主要記錄數據庫的變化情況,內容包括數據庫所有的更新操作恭理。所有涉及數據變動的操作拯辙,都要記錄進二進制日志中。因此有了binlog可以很方便的對數據進行復制和備份颜价,因而也常用作主從庫的同步涯保。

這里binlog所存儲的內容看起來似乎與redo log很相似,但是其實不然周伦。redo log是一種物理日志夕春,記錄的是實際上對某個數據進行了怎么樣的修改;而binlog是邏輯日志专挪,記錄的是SQL語句的原始邏輯及志,比如”給ID=2這一行的a字段加1 "片排。binlog日志中的內容是二進制的,根據日記格式參數的不同速侈,可能基于SQL語句划纽、基于數據本身或者二者的混合。一般常用記錄的都是SQL語句锌畸。

這里的物理和邏輯的概念,我的個人理解是:

物理的日志可看作是實際數據庫中數據頁上的變化信息靖避,只看重結果潭枣,而不在乎是通過“何種途徑”導致了這種結果;
邏輯的日志可看作是通過了某一種方法或者操作手段導致數據發(fā)生了變化幻捏,存儲的是邏輯性的操作盆犁。

同時,redo log是基于crash recovery篡九,保證MySQL宕機后的數據恢復谐岁;而binlog是基于point-in-time recovery,保證服務器可以基于時間點對數據進行恢復榛臼,或者對數據進行備份伊佃。

事實上最開始MySQL是沒有redo log日志的。因為起先MySQL是沒有InnoDB引擎的沛善,自帶的引擎是MyISAM航揉。binlog是服務層的日志,因此所有引擎都能夠使用金刁。但是光靠binlog日志只能提供歸檔的作用帅涂,無法提供crash-safe能力,所以InnoDB引擎就采用了學自于Oracle的技術尤蛮,也就是redo log媳友,這才擁有了crash-safe能力。這里對redo log日志和binlog日志的特點分別進行了對比:

在MySQL執(zhí)行更新語句時产捞,都會涉及到redo log日志和binlog日志的讀寫醇锚。一條更新語句的執(zhí)行過程如下:

MySQL更新語句的執(zhí)行過程從上圖可以看出,MySQL在執(zhí)行更新語句的時候轧葛,在服務層進行語句的解析和執(zhí)行搂抒,在引擎層進行數據的提取和存儲;同時在服務層對binlog進行寫入尿扯,在InnoDB內進行redo log的寫入求晶。

不僅如此,在對redo log寫入時有兩個階段的提交衷笋,一是binlog寫入之前prepare狀態(tài)的寫入芳杏,二是binlog寫入之后commit狀態(tài)的寫入矩屁。

之所以要安排這么一個兩階段提交,自然是有它的道理的【粽裕現在我們可以假設不采用兩階段提交的方式吝秕,而是采用“單階段”進行提交,即要么先寫入redo log空幻,后寫入binlog烁峭;要么先寫入binlog,后寫入redo log秕铛。這兩種方式的提交都會導致原先數據庫的狀態(tài)和被恢復后的數據庫的狀態(tài)不一致约郁。

先寫入redo log,后寫入binlog:

在寫完redo log之后但两,數據此時具有crash-safe能力鬓梅,因此系統崩潰,數據會恢復成事務開始之前的狀態(tài)谨湘。但是绽快,若在redo log寫完時候,binlog寫入之前紧阔,系統發(fā)生了宕機坊罢。此時binlog沒有對上面的更新語句進行保存,導致當使用binlog進行數據庫的備份或者恢復時寓辱,就少了上述的更新語句艘绍。從而使得id=2這一行的數據沒有被更新。

先寫入binlog秫筏,后寫入redo log:

寫完binlog之后诱鞠,所有的語句都被保存,所以通過binlog復制或恢復出來的數據庫中id=2這一行的數據會被更新為a=1这敬。但是如果在redo log寫入之前航夺,系統崩潰,那么redo log中記錄的這個事務會無效崔涂,導致實際數據庫中id=2這一行的數據并沒有更新阳掐。

先寫binlog后寫redo log的問題由此可見,兩階段的提交就是為了避免上述的問題冷蚂,使得binlog和redo log中保存的信息是一致的缭保。

回滾日志(undo log)

回滾日志同樣也是InnoDB引擎提供的日志,顧名思義蝙茶,回滾日志的作用就是對數據進行回滾艺骂。當事務對數據庫進行修改,InnoDB引擎不僅會記錄redo log隆夯,還會生成對應的undo log日志钳恕;如果事務執(zhí)行失敗或調用了rollback别伏,導致事務需要回滾,就可以利用undo log中的信息將數據回滾到修改之前的樣子忧额。

但是undo log不redo log不一樣厘肮,它屬于邏輯日志。它對SQL語句執(zhí)行相關的信息進行記錄睦番。當發(fā)生回滾時类茂,InnoDB引擎會根據undo log日志中的記錄做與之前相反的工作。比如對于每個數據插入操作(insert)托嚣,回滾時會執(zhí)行數據刪除操作(delete)大咱;對于每個數據刪除操作(delete),回滾時會執(zhí)行數據插入操作(insert)注益;對于每個數據更新操作(update),回滾時會執(zhí)行一個相反的數據更新操作(update)溯捆,把數據改回去丑搔。undo log由兩個作用,一是提供回滾提揍,二是實現MVCC啤月。

五、主從復制

主從復制的概念很簡單劳跃,就是從原來的數據庫復制一個完全一樣的數據庫谎仲,原來的數據庫稱作主數據庫,復制的數據庫稱為從數據庫刨仑。從數據庫會與主數據庫進行數據同步郑诺,保持二者的數據一致性。

主從復制的原理實際上就是通過bin log日志實現的杉武。bin log日志中保存了數據庫中所有SQL語句辙诞,通過對bin log日志中SQL的復制,然后再進行語句的執(zhí)行即可實現從數據庫與主數據庫的同步轻抱。

主從復制的過程可見下圖飞涂。主從復制的過程主要是靠三個線程進行的,一個運行在主服務器中的發(fā)送線程祈搜,用于發(fā)送binlog日志到從服務器较店。兩外兩個運行在從服務器上的I/O線程和SQL線程。I/O線程用于讀取主服務器發(fā)送過來的binlog日志內容容燕,并拷貝到本地的中繼日志中梁呈。SQL線程用于讀取中繼日志中關于數據更新的SQL語句并執(zhí)行,從而實現主從庫的數據一致缰趋。

之所以需要實現主從復制捧杉,實際上是由實際應用場景所決定的陕见。主從復制能夠帶來的好處有:

1.通過復制實現數據的異地備份,當主數據庫故障時味抖,可切換從數據庫评甜,避免數據丟失。
2.可實現架構的擴展仔涩,當業(yè)務量越來越大忍坷,I/O訪問頻率過高時,采用多庫的存儲熔脂,可以降低磁盤I/O訪問的頻率佩研,提高單個機器的I/O性能。
3.可實現讀寫分離霞揉,使數據庫能支持更大的并發(fā)旬薯。
4.實現服務器的負載均衡,通過在主服務器和從服務器之間切分處理客戶查詢的負荷适秩。

六绊序、總結

MySQL數據庫應該算是程序員必須掌握的技術之一了。無論是項目過程中還是面試中秽荞,MySQL都是非常重要的基礎知識骤公。不過,對于MySQL來說扬跋,真的東西太多了阶捆。我在寫這篇文章的時候,查閱了大量的資料钦听,發(fā)現越看不懂的越多洒试。還真是應了那句話:

你知道的越多,不知道的也就越多朴上。

這篇文章著重是從理論的角度去解析MySQL基本的事務和日志系統的基本原理儡司,我在表述的時候盡可能的避免采用實際的代碼去描述。即便是這篇將近一萬字+近二十副純手工繪制的圖解余指,也難以將MySQL的博大精深分析透徹捕犬。

但是我相信,對于初學者而言酵镜,這些理論能夠讓你對MySQL有一個整體的感知碉碉,讓你對“何謂關系型數據庫”這么一個問題有了比較清晰的認知;而對于熟練掌握MySQL的大佬來說淮韭,或許本文也能夠喚醒你塵封已久的底層理論基礎垢粮,對你之后的面試也會有一定幫助。

技術這種東西沒有絕對的對錯靠粪,倘若文中有誤還請諒解蜡吧,并歡迎與我討論毫蚓。自主思考永遠比被動接受更有效。

寫在最后

歡迎大家關注我的公眾號【風平浪靜如碼】昔善,海量Java相關文章元潘,學習資料都會在里面更新,整理的資料也會放在里面君仆。

覺得寫的還不錯的就點個贊翩概,加個關注唄!點關注返咱,不迷路钥庇,持續(xù)更新!? 评姨!

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市萤晴,隨后出現的幾起案子参咙,更是在濱河造成了極大的恐慌,老刑警劉巖硫眯,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異择同,居然都是意外死亡两入,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門敲才,熙熙樓的掌柜王于貴愁眉苦臉地迎上來裹纳,“玉大人,你說我怎么就攤上這事紧武√暄酰” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵阻星,是天一觀的道長朋鞍。 經常有香客問我,道長妥箕,這世上最難降的妖魔是什么滥酥? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮畦幢,結果婚禮上坎吻,老公的妹妹穿的比我還像新娘。我一直安慰自己宇葱,他們只是感情好瘦真,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布刊头。 她就那樣靜靜地躺著,像睡著了一般诸尽。 火紅的嫁衣襯著肌膚如雪原杂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天弦讽,我揣著相機與錄音污尉,去河邊找鬼。 笑死往产,一個胖子當著我的面吹牛被碗,可吹牛的內容都是我干的。 我是一名探鬼主播仿村,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼锐朴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蔼囊?” 一聲冷哼從身側響起焚志,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎畏鼓,沒想到半個月后酱酬,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡云矫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年膳沽,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片让禀。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡挑社,死狀恐怖,靈堂內的尸體忽然破棺而出巡揍,到底是詐尸還是另有隱情痛阻,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布腮敌,位于F島的核電站阱当,受9級特大地震影響,放射性物質發(fā)生泄漏糜工。R本人自食惡果不足惜斗这,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望啤斗。 院中可真熱鬧表箭,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至极舔,卻和暖如春凤覆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拆魏。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工盯桦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人渤刃。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓拥峦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親卖子。 傳聞我的和親對象是個殘疾皇子略号,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內容