久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL事務(wù)日志的特征有哪些

共計(jì) 7912 個(gè)字符,預(yù)計(jì)需要花費(fèi) 20 分鐘才能閱讀完成。

本篇內(nèi)容主要講解“MySQL 事務(wù)日志的特征有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓丸趣 TV 小編來帶大家學(xué)習(xí)“MySQL 事務(wù)日志的特征有哪些”吧!

一、MySQL 事務(wù)

事務(wù)是 MySQL 區(qū)別于 NoSQL 的重要特征,是保證關(guān)系型數(shù)據(jù)庫(kù)數(shù)據(jù)一致性的關(guān)鍵技術(shù)。事務(wù)可看作是對(duì)數(shù)據(jù)庫(kù)操作的基本執(zhí)行單元,可能包含一個(gè)或者多個(gè) SQL 語句。這些語句在執(zhí)行時(shí),要么都執(zhí)行,要么都不執(zhí)行。

事務(wù)的執(zhí)行主要包括兩個(gè)操作,提交和回滾。

提交:commit,將事務(wù)執(zhí)行結(jié)果寫入數(shù)據(jù)庫(kù)。

回滾:rollback,回滾所有已經(jīng)執(zhí)行的語句,返回修改之前的數(shù)據(jù)。

MySQL 事務(wù)包含四個(gè)特性,號(hào)稱 ACID 四大天王。

原子性(Atomicity):語句要么全執(zhí)行,要么全不執(zhí)行,是事務(wù)最核心的特性,事務(wù)本身就是以原子性來定義的;實(shí)現(xiàn)主要基于 undo log 日志實(shí)現(xiàn)的。

持久性(Durability  :保證事務(wù)提交后不會(huì)因?yàn)殄礄C(jī)等原因?qū)е聰?shù)據(jù)丟失;實(shí)現(xiàn)主要基于 redo log 日志。

隔離性(Isolation):保證事務(wù)執(zhí)行盡可能不受其他事務(wù)影響;InnoDB 默認(rèn)的隔離級(jí)別是 RR,RR 的實(shí)現(xiàn)主要基于鎖機(jī)制、數(shù)據(jù)的隱藏列、undo log 和類 next-key lock 機(jī)制。

一致性(Consistency):事務(wù)追求的最終目標(biāo),一致性的實(shí)現(xiàn)既需要數(shù)據(jù)庫(kù)層面的保障,也需要應(yīng)用層面的保障。

原子性

事務(wù)的原子性就如原子操作一般,表示事務(wù)不可再分,其中的操作要么都做,要么都不做;如果事務(wù)中一個(gè) SQL 語句執(zhí)行失敗,則已執(zhí)行的語句也必須回滾,數(shù)據(jù)庫(kù)退回到事務(wù)前的狀態(tài)。只有 0 和 1,沒有其它值。

事務(wù)的原子性表明事務(wù)就是一個(gè)整體,當(dāng)事務(wù)無法成功執(zhí)行的時(shí)候,需要將事務(wù)中已經(jīng)執(zhí)行過的語句全部回滾,使得數(shù)據(jù)庫(kù)回歸到最初未開始事務(wù)的狀態(tài)。

事務(wù)的原子性就是通過 undo log 日志進(jìn)行實(shí)現(xiàn)的。當(dāng)事務(wù)需要進(jìn)行回滾時(shí),InnoDB 引擎就會(huì)調(diào)用 undo log 日志進(jìn)行 SQL 語句的撤銷,實(shí)現(xiàn)數(shù)據(jù)的回滾。

持久性

事務(wù)的持久性是指當(dāng)事務(wù)提交之后,數(shù)據(jù)庫(kù)的改變就應(yīng)該是永久性的,而不是暫時(shí)的。這也就是說,當(dāng)事務(wù)提交之后,任何其它操作甚至是系統(tǒng)的宕機(jī)故障都不會(huì)對(duì)原來事務(wù)的執(zhí)行結(jié)果產(chǎn)生影響。

事務(wù)的持久性是通過 InnoDB 存儲(chǔ)引擎中的 redo log 日志來實(shí)現(xiàn)的,具體實(shí)現(xiàn)思路見下文。

隔離性

原子性和持久性是單個(gè)事務(wù)本身層面的性質(zhì),而隔離性是指事務(wù)之間應(yīng)該保持的關(guān)系。隔離性要求不同事務(wù)之間的影響是互不干擾的,一個(gè)事務(wù)的操作與其它事務(wù)是相互隔離的。

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

鎖機(jī)制

事務(wù)之間的隔離,是通過鎖機(jī)制實(shí)現(xiàn)的。當(dāng)一個(gè)事務(wù)需要對(duì)數(shù)據(jù)庫(kù)中的某行數(shù)據(jù)進(jìn)行修改時(shí),需要先給數(shù)據(jù)加鎖;加了鎖的數(shù)據(jù),其它事務(wù)是不運(yùn)行操作的,只能等待當(dāng)前事務(wù)提交或回滾將鎖釋放。

鎖機(jī)制并不是一個(gè)陌生的概念,在許多場(chǎng)景中都會(huì)利用到不同實(shí)現(xiàn)的鎖對(duì)數(shù)據(jù)進(jìn)行保護(hù)和同步。而在 MySQL 中,根據(jù)不同的劃分標(biāo)準(zhǔn),還可將鎖分為不同的種類。

按照粒度劃分:行鎖、表鎖、頁(yè)鎖

按照使用方式劃分:共享鎖、排它鎖

按照思想劃分:悲觀鎖、樂觀鎖

鎖機(jī)制的知識(shí)點(diǎn)很多,由于篇幅不好全部展開講。這里對(duì)按照粒度劃分的鎖進(jìn)行簡(jiǎn)單介紹。

粒度:指數(shù)據(jù)倉(cāng)庫(kù)的數(shù)據(jù)單位中保存數(shù)據(jù)的細(xì)化或綜合程度的級(jí)別。細(xì)化程度越高,粒度級(jí)就越小;相反,細(xì)化程度越低,粒度級(jí)就越大。

MySQL 按照鎖的粒度劃分可以分為行鎖、表鎖和頁(yè)鎖。

行鎖:粒度最小的鎖,表示只針對(duì)當(dāng)前操作的行進(jìn)行加鎖;

表鎖:粒度最大的鎖,表示當(dāng)前的操作對(duì)整張表加鎖;

頁(yè)鎖:粒度介于行級(jí)鎖和表級(jí)鎖中間的一種鎖,表示對(duì)頁(yè)進(jìn)行加鎖。

數(shù)據(jù)庫(kù)的粒度劃分

這三種鎖是在不同層次上對(duì)數(shù)據(jù)進(jìn)行鎖定,由于粒度的不同,其帶來的好處和劣勢(shì)也不一而同。

表鎖在操作數(shù)據(jù)時(shí)會(huì)鎖定整張表,因而并發(fā)性能較差;

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

MySQL 中不同的存儲(chǔ)引擎能夠支持的鎖也是不一樣的。MyIsam 只支持表鎖,而 InnoDB 同時(shí)支持表鎖和行鎖,且出于性能考慮,絕大多數(shù)情況下使用的都是行鎖。

并發(fā)讀寫問題

在并發(fā)情況下,MySQL 的同時(shí)讀寫可能會(huì)導(dǎo)致三類問題,臟讀、不可重復(fù)度和幻讀。

(1)臟讀:當(dāng)前事務(wù)中讀到其他事務(wù)未提交的數(shù)據(jù),也就是臟數(shù)據(jù)。

以上圖為例,事務(wù) A 在讀取文章的閱讀量時(shí),讀取到了事務(wù) B 為提交的數(shù)據(jù)。如果事務(wù) B 最后沒有順利提交,導(dǎo)致事務(wù)回滾,那么實(shí)際上閱讀量并沒有修改成功,而事務(wù) A 卻是讀到的修改后的值,顯然不合情理。

(2)不可重復(fù)讀:在事務(wù) A 中先后兩次讀取同一個(gè)數(shù)據(jù),但是兩次讀取的結(jié)果不一樣。臟讀與不可重復(fù)讀的區(qū)別在于:前者讀到的是其他事務(wù)未提交的數(shù)據(jù),后者讀到的是其他事務(wù)已提交的數(shù)據(jù)。

以上圖為例,事務(wù) A 在先后讀取文章閱讀量的數(shù)據(jù)時(shí),結(jié)果卻不一樣。說明事務(wù) A 在執(zhí)行的過程中,閱讀量的值被其它事務(wù)給修改了。這樣使得數(shù)據(jù)的查詢結(jié)果不再可靠,同樣也不合實(shí)際。

(3)幻讀:在事務(wù) A 中按照某個(gè)條件先后兩次查詢數(shù)據(jù)庫(kù),兩次查詢結(jié)果的行數(shù)不同,這種現(xiàn)象稱為幻讀。不可重復(fù)讀與幻讀的區(qū)別可以通俗的理解為:前者是數(shù)據(jù)變了,后者是數(shù)據(jù)的行數(shù)變了。

以上圖為例,當(dāng)對(duì) 0 閱讀量 100 的文章進(jìn)行查詢時(shí),先查到了一個(gè)結(jié)果,后來查詢到了兩個(gè)結(jié)果。這表明同一個(gè)事務(wù)的查詢結(jié)果數(shù)不一,行數(shù)不一致。這樣的問題使得在根據(jù)某些條件對(duì)數(shù)據(jù)篩選的時(shí)候,前后篩選結(jié)果不具有可靠性。

隔離級(jí)別

根據(jù)上面這三種問題,產(chǎn)生了四種隔離級(jí)別,表明數(shù)據(jù)庫(kù)不同程度的隔離性質(zhì)。

在實(shí)際的數(shù)據(jù)庫(kù)設(shè)計(jì)中,隔離級(jí)別越高,導(dǎo)致數(shù)據(jù)庫(kù)的并發(fā)效率會(huì)越低;而隔離級(jí)別太低,又會(huì)導(dǎo)致數(shù)據(jù)庫(kù)在讀寫過程中會(huì)遇到各種亂七八糟的問題。

因此在大多數(shù)數(shù)據(jù)庫(kù)系統(tǒng)中,默認(rèn)的隔離級(jí)別時(shí)讀已提交(如 Oracle)或者可重復(fù)讀 RR(MySQL 的 InnoDB 引擎)。

MVCC

又是一個(gè)難嚼的大塊頭。MVCC 就是用來實(shí)現(xiàn)上面的第三個(gè)隔離級(jí)別,可重復(fù)讀 RR。

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

MVCC 的特點(diǎn)就是在同一時(shí)刻,不同事務(wù)可以讀取到不同版本的數(shù)據(jù),從而可以解決臟讀和不可重復(fù)讀的問題。

MVCC 實(shí)際上就是通過數(shù)據(jù)的隱藏列和回滾日志(undo log),實(shí)現(xiàn)多個(gè)版本數(shù)據(jù)的共存。這樣的好處是,使用 MVCC 進(jìn)行讀數(shù)據(jù)的時(shí)候,不用加鎖,從而避免了同時(shí)讀寫的沖突。

在實(shí)現(xiàn) MVCC 時(shí),每一行的數(shù)據(jù)中會(huì)額外保存幾個(gè)隱藏的列,比如當(dāng)前行創(chuàng)建時(shí)的版本號(hào)和刪除時(shí)間和指向 undo log 的回滾指針。這里的版本號(hào)并不是實(shí)際的時(shí)間值,而是系統(tǒng)版本號(hào)。每開始新的事務(wù),系統(tǒng)版本號(hào)都會(huì)自動(dòng)遞增。事務(wù)開始時(shí)的系統(tǒng)版本號(hào)會(huì)作為事務(wù)的版本號(hào),用來和查詢每行記錄的版本號(hào)進(jìn)行比較。

每個(gè)事務(wù)又有自己的版本號(hào),這樣事務(wù)內(nèi)執(zhí)行數(shù)據(jù)操作時(shí),就通過版本號(hào)的比較來達(dá)到數(shù)據(jù)版本控制的目的。

另外,InnoDB 實(shí)現(xiàn)的隔離級(jí)別 RR 時(shí)可以避免幻讀現(xiàn)象的,這是通過 next-key lock 機(jī)制實(shí)現(xiàn)的。

next-key lock 實(shí)際上就是行鎖的一種,只不過它不只是會(huì)鎖住當(dāng)前行記錄的本身,還會(huì)鎖定一個(gè)范圍。比如上面幻讀的例子,開始查詢 0 閱讀量 100 的文章時(shí),只查到了一個(gè)結(jié)果。next-key lock 會(huì)將查詢出的這一行進(jìn)行鎖定,同時(shí)還會(huì)對(duì) 0 閱讀量 100 這個(gè)范圍進(jìn)行加鎖,這實(shí)際上是一種間隙鎖。間隙鎖能夠防止其他事務(wù)在這個(gè)間隙修改或者插入記錄。這樣一來,就保證了在 0 閱讀量 100 這個(gè)間隙中,只存在原來的一行數(shù)據(jù),從而避免了幻讀。

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

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

首先提一個(gè)問題:

在 T6 時(shí)間,事務(wù) A 提交事務(wù)之后,猜一猜文章 A 和文章 B 的閱讀量為多少?

答案是,文章 AB 的閱讀量都被修改成了 10000。這代表著事務(wù) B 的提交實(shí)際上對(duì)事務(wù) A 的執(zhí)行產(chǎn)生了影響,表明兩個(gè)事務(wù)之間并不是完全隔離的。雖然能夠避免幻讀現(xiàn)象,但是卻沒有達(dá)到可串行化的級(jí)別。

這還說明,避免臟讀、不可重復(fù)讀和幻讀,是達(dá)到可串行化的隔離級(jí)別的必要不充分條件。可串行化是都能夠避免臟讀、不可重復(fù)讀和幻讀,但是避免臟讀、不可重復(fù)讀和幻讀卻不一定達(dá)到了可串行化。

一致性

一致性是指事務(wù)執(zhí)行結(jié)束后,數(shù)據(jù)庫(kù)的完整性約束沒有被破壞,事務(wù)執(zhí)行的前后都是合法的數(shù)據(jù)狀態(tài)。

一致性是事務(wù)追求的最終目標(biāo),原子性、持久性和隔離性,實(shí)際上都是為了保證數(shù)據(jù)庫(kù)狀態(tài)的一致性而存在的。

這就不多說了吧。你細(xì)品。

二、MySQL 日志系統(tǒng)

了解完 MySQL 的基本架構(gòu),大體上能夠?qū)?MySQL 的執(zhí)行流程有了比較清晰的認(rèn)知。接下來我將為大家介紹一下日志系統(tǒng)。

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

MySQL 的日志有很多種,如二進(jìn)制日志(binlog)、錯(cuò)誤日志、查詢?nèi)罩尽⒙樵內(nèi)罩镜龋送?InnoDB 存儲(chǔ)引擎還提供了兩種日志:redo log(重做日志)和 undo log(回滾日志)。這里將重點(diǎn)針對(duì) InnoDB 引擎,對(duì)重做日志、回滾日志和二進(jìn)制日志這三種進(jìn)行分析。

重做日志(redo log)

重做日志(redo log)是 InnoDB 引擎層的日志,用來記錄事務(wù)操作引起數(shù)據(jù)的變化,記錄的是數(shù)據(jù)頁(yè)的物理修改。

重做日記的作用其實(shí)很好理解,我打個(gè)比方。數(shù)據(jù)庫(kù)中數(shù)據(jù)的修改就好比你寫的論文,萬一哪天論文丟了怎么呢?以防這種不幸的發(fā)生,我們可以在寫論文的時(shí)候,每一次修改都拿個(gè)小本本記錄一下,記錄什么時(shí)間對(duì)某一頁(yè)進(jìn)行了怎么樣的修改。這就是重做日志。

InnoDB 引擎對(duì)數(shù)據(jù)的更新,是先將更新記錄寫入 redo log 日志,然后會(huì)在系統(tǒng)空閑的時(shí)候或者是按照設(shè)定的更新策略再將日志中的內(nèi)容更新到磁盤之中。這就是所謂的預(yù)寫式技術(shù)(Write Ahead logging)。這種技術(shù)可以大大減少 IO 操作的頻率,提升數(shù)據(jù)刷新的效率。

臟數(shù)據(jù)刷盤

值得注意的是,redo log 日志的大小是固定的,為了能夠持續(xù)不斷的對(duì)更新記錄進(jìn)行寫入,在 redo log 日志中設(shè)置了兩個(gè)標(biāo)志位置,checkpoint 和 write_pos,分別表示記錄擦除的位置和記錄寫入的位置。redo log 日志的數(shù)據(jù)寫入示意圖可見下圖。

當(dāng) write_pos 標(biāo)志到了日志結(jié)尾時(shí),會(huì)從結(jié)尾跳至日志頭部進(jìn)行重新循環(huán)寫入。所以 redo log 的邏輯結(jié)構(gòu)并不是線性的,而是可看作一個(gè)圓周運(yùn)動(dòng)。write_pos 與 checkpoint 中間的空間可用于寫入新數(shù)據(jù),寫入和擦除都是往后推移,循環(huán)往復(fù)的。

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

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

臟數(shù)據(jù):指內(nèi)存中未刷到磁盤的數(shù)據(jù)。

redo log 中最重要的概念就是緩沖池 buffer pool,這是在內(nèi)存中分配的一個(gè)區(qū)域,包含了磁盤中部分?jǐn)?shù)據(jù)頁(yè)的映射,作為訪問數(shù)據(jù)庫(kù)的緩沖。

當(dāng)請(qǐng)求讀取數(shù)據(jù)時(shí),會(huì)先判斷是否在緩沖池命中,如果未命中才會(huì)在磁盤上進(jìn)行檢索后放入緩沖池;

當(dāng)請(qǐng)求寫入數(shù)據(jù)時(shí),會(huì)先寫入緩沖池,緩沖池中修改的數(shù)據(jù)會(huì)定期刷新到磁盤中。這一過程也被稱之為刷臟。

因此,當(dāng)數(shù)據(jù)修改時(shí),除了修改 buffer pool 中的數(shù)據(jù),還會(huì)在 redo log 中記錄這次操作;當(dāng)事務(wù)提交時(shí),會(huì)根據(jù) redo log 的記錄對(duì)數(shù)據(jù)進(jìn)行刷盤。如果 MySQL 宕機(jī),重啟時(shí)可以讀取 redo log 中的數(shù)據(jù),對(duì)數(shù)據(jù)庫(kù)進(jìn)行恢復(fù),從而保證了事務(wù)的持久性,使得數(shù)據(jù)庫(kù)獲得 crash-safe 能力。

臟日志刷盤

除了上面提到的對(duì)于臟數(shù)據(jù)的刷盤,實(shí)際上 redo log 日志在記錄時(shí),為了保證日志文件的持久化,也需要經(jīng)歷將日志記錄從內(nèi)存寫入到磁盤的過程。redo log 日志可分為兩個(gè)部分,一是存在易失性內(nèi)存中的緩存日志 redo log buff,二是保存在磁盤上的 redo log 日志文件 redo log file。

為了確保每次記錄都能夠?qū)懭氲酱疟P中的日志中,每次將 redo log buffer 中的日志寫入 redo log file 的過程中都會(huì)調(diào)用一次操作系統(tǒng)的 fsync 操作。

fsync 函數(shù):包含在 UNIX 系統(tǒng)頭文件 #include unistd.h 中,用于同步內(nèi)存中所有已修改的文件數(shù)據(jù)到儲(chǔ)存設(shè)備。

在寫入的過程中,還需要經(jīng)過操作系統(tǒng)內(nèi)核空間的 os buffer。redo log 日志的寫入過程可見下圖。

redo log 日志刷盤流程

二進(jìn)制日志(binlog)

二進(jìn)制日志 binlog 是服務(wù)層的日志,還被稱為歸檔日志。binlog 主要記錄數(shù)據(jù)庫(kù)的變化情況,內(nèi)容包括數(shù)據(jù)庫(kù)所有的更新操作。所有涉及數(shù)據(jù)變動(dòng)的操作,都要記錄進(jìn)二進(jìn)制日志中。因此有了 binlog 可以很方便的對(duì)數(shù)據(jù)進(jìn)行復(fù)制和備份,因而也常用作主從庫(kù)的同步。

這里 binlog 所存儲(chǔ)的內(nèi)容看起來似乎與 redo log 很相似,但是其實(shí)不然。redo log 是一種物理日志,記錄的是實(shí)際上對(duì)某個(gè)數(shù)據(jù)進(jìn)行了怎么樣的修改;而 binlog 是邏輯日志,記錄的是 SQL 語句的原始邏輯,比如”給 ID= 2 這一行的 a 字段加 1。binlog 日志中的內(nèi)容是二進(jìn)制的,根據(jù)日記格式參數(shù)的不同,可能基于 SQL 語句、基于數(shù)據(jù)本身或者二者的混合。一般常用記錄的都是 SQL 語句。

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

物理的日志可看作是實(shí)際數(shù)據(jù)庫(kù)中數(shù)據(jù)頁(yè)上的變化信息,只看重結(jié)果,而不在乎是通過“何種途徑”導(dǎo)致了這種結(jié)果;

邏輯的日志可看作是通過了某一種方法或者操作手段導(dǎo)致數(shù)據(jù)發(fā)生了變化,存儲(chǔ)的是邏輯性的操作。

同時(shí),redo log 是基于 crash recovery,保證 MySQL 宕機(jī)后的數(shù)據(jù)恢復(fù);而 binlog 是基于 point-in-time recovery,保證服務(wù)器可以基于時(shí)間點(diǎn)對(duì)數(shù)據(jù)進(jìn)行恢復(fù),或者對(duì)數(shù)據(jù)進(jìn)行備份。

事實(shí)上最開始 MySQL 是沒有 redo log 日志的。因?yàn)槠鹣?MySQL 是沒有 InnoDB 引擎的,自帶的引擎是 MyISAM。binlog 是服務(wù)層的日志,因此所有引擎都能夠使用。但是光靠 binlog 日志只能提供歸檔的作用,無法提供 crash-safe 能力,所以 InnoDB 引擎就采用了學(xué)自于 Oracle 的技術(shù),也就是 redo log,這才擁有了 crash-safe 能力。這里對(duì) redo log 日志和 binlog 日志的特點(diǎn)分別進(jìn)行了對(duì)比:

MySQL 事務(wù)日志的特征有哪些

redo log 與 binlog 的特點(diǎn)比較

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

MySQL 事務(wù)日志的特征有哪些

MySQL 更新語句的執(zhí)行過程

從上圖可以看出,MySQL 在執(zhí)行更新語句的時(shí)候,在服務(wù)層進(jìn)行語句的解析和執(zhí)行,在引擎層進(jìn)行數(shù)據(jù)的提取和存儲(chǔ);同時(shí)在服務(wù)層對(duì) binlog 進(jìn)行寫入,在 InnoDB 內(nèi)進(jìn)行 redo log 的寫入。

不僅如此,在對(duì) redo log 寫入時(shí)有兩個(gè)階段的提交,一是 binlog 寫入之前 prepare 狀態(tài)的寫入,二是 binlog 寫入之后 commit 狀態(tài)的寫入。

之所以要安排這么一個(gè)兩階段提交,自然是有它的道理的。現(xiàn)在我們可以假設(shè)不采用兩階段提交的方式,而是采用“單階段”進(jìn)行提交,即要么先寫入 redo log,后寫入 binlog;要么先寫入 binlog,后寫入 redo log。這兩種方式的提交都會(huì)導(dǎo)致原先數(shù)據(jù)庫(kù)的狀態(tài)和被恢復(fù)后的數(shù)據(jù)庫(kù)的狀態(tài)不一致。

先寫入 redo log,后寫入 binlog:

在寫完 redo log 之后,數(shù)據(jù)此時(shí)具有 crash-safe 能力,因此系統(tǒng)崩潰,數(shù)據(jù)會(huì)恢復(fù)成事務(wù)開始之前的狀態(tài)。但是,若在 redo log 寫完時(shí)候,binlog 寫入之前,系統(tǒng)發(fā)生了宕機(jī)。此時(shí) binlog 沒有對(duì)上面的更新語句進(jìn)行保存,導(dǎo)致當(dāng)使用 binlog 進(jìn)行數(shù)據(jù)庫(kù)的備份或者恢復(fù)時(shí),就少了上述的更新語句。從而使得 id= 2 這一行的數(shù)據(jù)沒有被更新。

MySQL 事務(wù)日志的特征有哪些

先寫 redo log 后寫 binlog 的問題

先寫入 binlog,后寫入 redo log:

寫完 binlog 之后,所有的語句都被保存,所以通過 binlog 復(fù)制或恢復(fù)出來的數(shù)據(jù)庫(kù)中 id= 2 這一行的數(shù)據(jù)會(huì)被更新為 a =1。但是如果在 redo log 寫入之前,系統(tǒng)崩潰,那么 redo log 中記錄的這個(gè)事務(wù)會(huì)無效,導(dǎo)致實(shí)際數(shù)據(jù)庫(kù)中 id= 2 這一行的數(shù)據(jù)并沒有更新。

MySQL 事務(wù)日志的特征有哪些

先寫 binlog 后寫 redo log 的問題

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

回滾日志(undo log)

回滾日志同樣也是 InnoDB 引擎提供的日志,顧名思義,回滾日志的作用就是對(duì)數(shù)據(jù)進(jìn)行回滾。當(dāng)事務(wù)對(duì)數(shù)據(jù)庫(kù)進(jìn)行修改,InnoDB 引擎不僅會(huì)記錄 redo log,還會(huì)生成對(duì)應(yīng)的 undo log 日志;如果事務(wù)執(zhí)行失敗或調(diào)用了 rollback,導(dǎo)致事務(wù)需要回滾,就可以利用 undo log 中的信息將數(shù)據(jù)回滾到修改之前的樣子。

但是 undo log 不 redo log 不一樣,它屬于邏輯日志。它對(duì) SQL 語句執(zhí)行相關(guān)的信息進(jìn)行記錄。當(dāng)發(fā)生回滾時(shí),InnoDB 引擎會(huì)根據(jù) undo log 日志中的記錄做與之前相反的工作。比如對(duì)于每個(gè)數(shù)據(jù)插入操作(insert),回滾時(shí)會(huì)執(zhí)行數(shù)據(jù)刪除操作(delete);對(duì)于每個(gè)數(shù)據(jù)刪除操作(delete),回滾時(shí)會(huì)執(zhí)行數(shù)據(jù)插入操作(insert);對(duì)于每個(gè)數(shù)據(jù)更新操作(update),回滾時(shí)會(huì)執(zhí)行一個(gè)相反的數(shù)據(jù)更新操作(update),把數(shù)據(jù)改回去。undo log 由兩個(gè)作用,一是提供回滾,二是實(shí)現(xiàn) MVCC。

三、主從復(fù)制

主從復(fù)制的概念很簡(jiǎn)單,就是從原來的數(shù)據(jù)庫(kù)復(fù)制一個(gè)完全一樣的數(shù)據(jù)庫(kù),原來的數(shù)據(jù)庫(kù)稱作主數(shù)據(jù)庫(kù),復(fù)制的數(shù)據(jù)庫(kù)稱為從數(shù)據(jù)庫(kù)。從數(shù)據(jù)庫(kù)會(huì)與主數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)同步,保持二者的數(shù)據(jù)一致性。

主從復(fù)制的原理實(shí)際上就是通過 bin log 日志實(shí)現(xiàn)的。bin log 日志中保存了數(shù)據(jù)庫(kù)中所有 SQL 語句,通過對(duì) bin log 日志中 SQL 的復(fù)制,然后再進(jìn)行語句的執(zhí)行即可實(shí)現(xiàn)從數(shù)據(jù)庫(kù)與主數(shù)據(jù)庫(kù)的同步。

主從復(fù)制的過程可見下圖。主從復(fù)制的過程主要是靠三個(gè)線程進(jìn)行的,一個(gè)運(yùn)行在主服務(wù)器中的發(fā)送線程,用于發(fā)送 binlog 日志到從服務(wù)器。兩外兩個(gè)運(yùn)行在從服務(wù)器上的 I / O 線程和 SQL 線程。I/ O 線程用于讀取主服務(wù)器發(fā)送過來的 binlog 日志內(nèi)容,并拷貝到本地的中繼日志中。SQL 線程用于讀取中繼日志中關(guān)于數(shù)據(jù)更新的 SQL 語句并執(zhí)行,從而實(shí)現(xiàn)主從庫(kù)的數(shù)據(jù)一致。

MySQL 事務(wù)日志的特征有哪些

主從復(fù)制原理

之所以需要實(shí)現(xiàn)主從復(fù)制,實(shí)際上是由實(shí)際應(yīng)用場(chǎng)景所決定的。主從復(fù)制能夠帶來的好處有:

1. 通過復(fù)制實(shí)現(xiàn)數(shù)據(jù)的異地備份,當(dāng)主數(shù)據(jù)庫(kù)故障時(shí),可切換從數(shù)據(jù)庫(kù),避免數(shù)據(jù)丟失。

2. 可實(shí)現(xiàn)架構(gòu)的擴(kuò)展,當(dāng)業(yè)務(wù)量越來越大,I/ O 訪問頻率過高時(shí),采用多庫(kù)的存儲(chǔ),可以降低磁盤 I / O 訪問的頻率,提高單個(gè)機(jī)器的 I / O 性能。

3. 可實(shí)現(xiàn)讀寫分離,使數(shù)據(jù)庫(kù)能支持更大的并發(fā)。

4. 實(shí)現(xiàn)服務(wù)器的負(fù)載均衡,通過在主服務(wù)器和從服務(wù)器之間切分處理客戶查詢的負(fù)荷。

到此,相信大家對(duì)“MySQL 事務(wù)日志的特征有哪些”有了更深的了解,不妨來實(shí)際操作一番吧!這里是丸趣 TV 網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-07-15發(fā)表,共計(jì)7912字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請(qǐng)注明出處。
評(píng)論(沒有評(píng)論)
主站蜘蛛池模板: 天长市| 甘洛县| 涿州市| 信宜市| 博客| 正宁县| 当阳市| 高要市| 阳信县| 宜兴市| 康保县| 雷波县| 科技| 汝南县| 出国| 湖口县| 大理市| 西青区| 社旗县| 临湘市| 通辽市| 平湖市| 绥德县| 商洛市| 肇庆市| 绥化市| 油尖旺区| 兰西县| 巧家县| 常德市| 南京市| 济南市| 马山县| 喀喇| 米易县| 淮安市| 出国| 巴塘县| 丹巴县| 营口市| 临邑县|