小編給大家分享一下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 階段。
圖 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 了。
圖 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)
猜你還喜歡下面的內(nèi)容