MySQL中常見的日志問題有哪些-創(chuàng)新互聯(lián)

小編給大家分享一下MySQL中常見的日志問題有哪些,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

創(chuàng)新互聯(lián)公司專注于網(wǎng)站建設(shè)|企業(yè)網(wǎng)站維護(hù)|優(yōu)化|托管以及網(wǎng)絡(luò)推廣,積累了大量的網(wǎng)站設(shè)計(jì)與制作經(jīng)驗(yàn),為許多企業(yè)提供了網(wǎng)站定制設(shè)計(jì)服務(wù),案例作品覆蓋成都軟裝設(shè)計(jì)等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結(jié)合品牌形象的塑造,量身定制品質(zhì)網(wǎng)站。

MySQL 里有兩個(gè)日志,即:重做日志(redo log)和歸檔日志(binlog)。

其中,binlog 可以給備庫使用,也可以保存起來用于恢復(fù)數(shù)據(jù)庫歷史數(shù)據(jù)。它是實(shí)現(xiàn)在 server 層的,所有引擎可以共用。redo log 是 InnoDB 特有的日志,用來支持 crash-safe 能力。

你一定聽過 MySQL 事務(wù)的兩階段提交,指的就是在事務(wù)提交的時(shí)候,分成 prepare 和 commit 兩個(gè)階段。

如圖 1 所示為一個(gè)事務(wù)的執(zhí)行流程,你在最后三步可以看到,redo log 先 prepare 完成,再寫 binlog,最后才進(jìn)入 redo log commit 階段。

MySQL中常見的日志問題有哪些

圖 1 兩階段提交示意圖

這里,我要先和你解釋一個(gè)誤會(huì)式的問題:這個(gè)圖不就是一個(gè) update 語句的執(zhí)行流程嗎,怎么還會(huì)調(diào)用 commit 語句?

通常情況下,你會(huì)產(chǎn)生這個(gè)疑問的原因,在于把兩個(gè)“commit”的概念混淆了:

問題中的“commit 語句”,是指 MySQL 語法中,用于提交一個(gè)事務(wù)的命令。一般跟 begin/start transaction 配對(duì)使用。

而我們圖中用到的這個(gè)“commit 步驟”,指的是事務(wù)提交過程中的一個(gè)小步驟,也是最后一步。當(dāng)這個(gè)步驟執(zhí)行完成后,這個(gè)事務(wù)就提交完成了。

“commit 語句”執(zhí)行的時(shí)候,會(huì)包含“commit 步驟”。

而我們這個(gè)例子里面,沒有顯式地開啟事務(wù),因此這個(gè) update 語句自己就是一個(gè)事務(wù),在執(zhí)行完成后提交事務(wù)時(shí),就會(huì)用到這個(gè)“commit 步驟”。

接下來,我們就一起分析一下在兩階段提交的不同時(shí)刻,MySQL 異常重啟會(huì)出現(xiàn)什么現(xiàn)象。

如果在圖中時(shí)刻 A 的地方,也就是寫入 redo log 處于 prepare 階段之后、寫 binlog 之前,發(fā)生了崩潰(crash),由于此時(shí) binlog 還沒寫,redo log 也還沒提交,所以崩潰恢復(fù)的時(shí)候,這個(gè)事務(wù)會(huì)回滾。這時(shí)候,binlog 還沒寫,所以也不會(huì)傳到備庫。到這里,我們都可以理解。

而我們理解會(huì)出現(xiàn)問題的地方,主要集中在時(shí)刻 B,也就是 binlog 寫完,redo log 還沒 commit 前發(fā)生 crash,那崩潰恢復(fù)的時(shí)候 MySQL 會(huì)怎么處理?

我們先來看一下崩潰恢復(fù)時(shí)的判斷規(guī)則。

1、如果 redo log 里面的事務(wù)是完整的,也就是已經(jīng)有了 commit 標(biāo)識(shí),則直接提交;

2、如果 redo log 里面的事務(wù)只有完整的 prepare,則判斷對(duì)應(yīng)的事務(wù) binlog 是否存在并完整:

a.如果是,則提交事務(wù);

b.否則,回滾事務(wù)。

這里,時(shí)刻 B 發(fā)生 crash 對(duì)應(yīng)的就是 2(a) 的情況,崩潰恢復(fù)過程中事務(wù)會(huì)被提交。

現(xiàn)在,我們就針對(duì)兩階段提交再繼續(xù)延展一下。

問題 1:MySQL 怎么知道 binlog 是完整的?

回答:一個(gè)事務(wù)的 binlog 是有完整格式的:

如果碰到既有 prepare、又有 commit 的 redo log,就直接提交;

如果碰到只有 parepare、而沒有 commit 的 redo log,就拿著 XID 去 binlog 找對(duì)應(yīng)的事務(wù)。

問題 3:處于 prepare 階段的 redo log 加上完整 binlog,重啟就能恢復(fù),MySQL 為什么要這么設(shè)計(jì)?

回答:其實(shí),這個(gè)問題還是跟我們?cè)诜醋C法中說到的數(shù)據(jù)與備份的一致性有關(guān)。在時(shí)刻 B,也就是 binlog 寫完以后 MySQL 發(fā)生崩潰,這時(shí)候 binlog 已經(jīng)寫入了,之后就會(huì)被從庫(或者用這個(gè) binlog 恢復(fù)出來的庫)使用。

所以,在主庫上也要提交這個(gè)事務(wù)。采用這個(gè)策略,主庫和備庫的數(shù)據(jù)就保證了一致性。

問題 4:如果這樣的話,為什么還要兩階段提交呢?干脆先 redo log 寫完,再寫 binlog。崩潰恢復(fù)的時(shí)候,必須得兩個(gè)日志都完整才可以。是不是一樣的邏輯?

回答:其實(shí),兩階段提交是經(jīng)典的分布式系統(tǒng)問題,并不是 MySQL 獨(dú)有的。

如果必須要舉一個(gè)場(chǎng)景,來說明這么做的必要性的話,那就是事務(wù)的持久性問題。

對(duì)于 InnoDB 引擎來說,如果 redo log 提交完成了,事務(wù)就不能回滾(如果這還允許回滾,就可能覆蓋掉別的事務(wù)的更新)。而如果 redo log 直接提交,然后 binlog 寫入的時(shí)候失敗,InnoDB 又回滾不了,數(shù)據(jù)和 binlog 日志又不一致了。

兩階段提交就是為了給所有人一個(gè)機(jī)會(huì),當(dāng)每個(gè)人都說“我 ok”的時(shí)候,再一起提交。

問題 5:不引入兩個(gè)日志,也就沒有兩階段提交的必要了。只用 binlog 來支持崩潰恢復(fù),又能支持歸檔,不就可以了?

回答:我把這個(gè)問題再翻譯一下的話,是說只保留 binlog,然后可以把提交流程改成這樣:... -> “數(shù)據(jù)更新到內(nèi)存” -> “寫 binlog” -> “提交事務(wù)”,是不是也可以提供崩潰恢復(fù)的能力?

答案是不可以。

如果說歷史原因的話,那就是 InnoDB 并不是 MySQL 的原生存儲(chǔ)引擎。MySQL 的原生引擎是 MyISAM,設(shè)計(jì)之初就有沒有支持崩潰恢復(fù)。

InnoDB 在作為 MySQL 的插件加入 MySQL 引擎家族之前,就已經(jīng)是一個(gè)提供了崩潰恢復(fù)和事務(wù)支持的引擎了。

InnoDB 接入了 MySQL 后,發(fā)現(xiàn)既然 binlog 沒有崩潰恢復(fù)的能力,那就用 InnoDB 原有的 redo log 好了。

而如果說實(shí)現(xiàn)上的原因的話,就有很多了。就按照問題中說的,只用 binlog 來實(shí)現(xiàn)崩潰恢復(fù)的流程,我畫了一張示意圖,這里就沒有 redo log 了。

MySQL中常見的日志問題有哪些

圖 2 只用 binlog 支持崩潰恢復(fù)

這樣的流程下,binlog 還是不能支持崩潰恢復(fù)的。我說一個(gè)不支持的點(diǎn)吧:binlog 沒有能力恢復(fù)“數(shù)據(jù)頁”。

如果在圖中標(biāo)的位置,也就是 binlog2 寫完了,但是整個(gè)事務(wù)還沒有 commit 的時(shí)候,MySQL 發(fā)生了 crash。

重啟后,引擎內(nèi)部事務(wù) 2 會(huì)回滾,然后應(yīng)用 binlog2 可以補(bǔ)回來;但是對(duì)于事務(wù) 1 來說,系統(tǒng)已經(jīng)認(rèn)為提交完成了,不會(huì)再應(yīng)用一次 binlog1。

但是,InnoDB 引擎使用的是 WAL 技術(shù),執(zhí)行事務(wù)的時(shí)候,寫完內(nèi)存和日志,事務(wù)就算完成了。如果之后崩潰,要依賴于日志來恢復(fù)數(shù)據(jù)頁。

也就是說在圖中這個(gè)位置發(fā)生崩潰的話,事務(wù) 1 也是可能丟失了的,而且是數(shù)據(jù)頁級(jí)的丟失。此時(shí),binlog 里面并沒有記錄數(shù)據(jù)頁的更新細(xì)節(jié),是補(bǔ)不回來的。

你如果要說,那我優(yōu)化一下 binlog 的內(nèi)容,讓它來記錄數(shù)據(jù)頁的更改可以嗎?可以,但這其實(shí)就是又做了一個(gè) redo log 出來。

所以,至少現(xiàn)在的 binlog 能力,還不能支持崩潰恢復(fù)。

問題 6:那能不能反過來,只用 redo log,不要 binlog?

回答:如果只從崩潰恢復(fù)的角度來講是可以的。你可以把 binlog 關(guān)掉,這樣就沒有兩階段提交了,但系統(tǒng)依然是 crash-safe 的。

但是,如果你了解一下業(yè)界各個(gè)公司的使用場(chǎng)景的話,就會(huì)發(fā)現(xiàn)在正式的生產(chǎn)庫上,binlog 都是開著的。因?yàn)?binlog 有著 redo log 無法替代的功能。

一個(gè)是歸檔。redo log 是循環(huán)寫,寫到末尾是要回到開頭繼續(xù)寫的。這樣歷史日志沒法保留,redo log 也就起不到歸檔的作用。

一個(gè)就是 MySQL 系統(tǒng)依賴于 binlog。binlog 作為 MySQL 一開始就有的功能,被用在了很多地方。其中,MySQL 系統(tǒng)高可用的基礎(chǔ),就是 binlog 復(fù)制。

還有很多公司有異構(gòu)系統(tǒng)(比如一些數(shù)據(jù)分析系統(tǒng)),這些系統(tǒng)就靠消費(fèi) MySQL 的 binlog 來更新自己的數(shù)據(jù)。關(guān)掉 binlog 的話,這些下游系統(tǒng)就沒法輸入了。

總之,由于現(xiàn)在包括 MySQL 高可用在內(nèi)的很多系統(tǒng)機(jī)制都依賴于 binlog,所以“鳩占鵲巢” redo log 還做不到。你看,發(fā)展生態(tài)是多么重要。

最后,推薦你關(guān)注丁奇的《MySQL 實(shí)戰(zhàn) 45 講》專欄。在專欄里,丁奇會(huì)幫你梳理出學(xué)習(xí) MySQL 的主線知識(shí),比如事務(wù)、索引、鎖等,還會(huì)就開發(fā)過程中經(jīng)常遇到的具體問題和你分析討論,并且?guī)湍憷斫鈫栴}背后的本質(zhì)。你會(huì)收獲 MySQL 核心技術(shù)詳解與原理說明和 36 個(gè) MySQL 常見痛點(diǎn)問題解析。

statement 格式的 binlog,最后會(huì)有 COMMIT;

row 格式的 binlog,最后會(huì)有一個(gè) XID event。

另外,在 MySQL 5.6.2 版本以后,還引入了 binlog-checksum 參數(shù),用來驗(yàn)證 binlog 內(nèi)容的正確性。對(duì)于 binlog 日志由于磁盤原因,可能會(huì)在日志中間出錯(cuò)的情況,MySQL 可以通過校驗(yàn) checksum 的結(jié)果來發(fā)現(xiàn)。所以,MySQL 還是有辦法驗(yàn)證事務(wù) binlog 的完整性的。

問題 2:redo log 和 binlog 是怎么關(guān)聯(lián)起來的?

回答:它們有一個(gè)共同的數(shù)據(jù)字段,叫 XID。崩潰恢復(fù)的時(shí)候,會(huì)按順序掃描 redo log:

看完了這篇文章,相信你對(duì)MySQL中常見的日志問題有哪些有了一定的了解,想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)網(wǎng)站制作公司行業(yè)資訊頻道,感謝各位的閱讀!

本文題目:MySQL中常見的日志問題有哪些-創(chuàng)新互聯(lián)
文章地址:http://muchs.cn/article42/eepec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄、網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)公司、App設(shè)計(jì)、自適應(yīng)網(wǎng)站、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管