<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Mysql的binlog和relay-log到底長啥樣?

          共 3393字,需瀏覽 7分鐘

           ·

          2020-09-12 04:30

          上一篇mysql面試的文章之后收到不少朋友的意見,希望深入講講復(fù)制、日志的格式這些,今天,我們就來深挖一下mysql的復(fù)制機(jī)制到底有哪一些,以及binlog和relay-log的結(jié)構(gòu)到底是什么樣子的。

          binlog作用

          binlog的主要作用是記錄數(shù)據(jù)庫中表的更改,它只記錄改變數(shù)據(jù)的sql,不改變數(shù)據(jù)的sql不會寫入,比如select語句一般不會被記錄,因?yàn)樗麄儾粫?shù)據(jù)產(chǎn)生任何改動。

          用一個(gè)實(shí)際的場景看下binlog產(chǎn)生的過程,準(zhǔn)備sql:

          create?table?test(text?varchar(20));
          insert?into?test?values?('test_text');
          select?*?from?test;
          flush?logs;

          查看binlog

          show?binlog?events?in?'binlog.000029';

          顯示的結(jié)果如下:

          binlog

          另外,也可以使用mysqlbinlog工具來查看binlog的內(nèi)容:

          show?variables?like?'log_%';?#查看日志目錄
          mysqlbinlog?--short-form?--force-if-open?--base64-output=never?/usr/local/var/mysql/binlog.000029

          從日志我們可以看到執(zhí)行了創(chuàng)建表的語句以及一個(gè)Format_desc頭和Ratate輪換事件,這個(gè)我們會在后面講到,先看幾個(gè)字段代表的含義。

          Log_name代表日志文件的名稱,比如我這里的查詢是直接查詢binlog.000029,默認(rèn)的寫法是show binlog events,但是這樣只會查詢到第一個(gè)binlog,并不是當(dāng)前激活狀態(tài)的binlog,如果你不知道binlog有哪些,可以用命令:

          show?binary?logs;?#查看binlog列表
          show?master?status;?#查看最新的binlog

          Pos代表文件開始的位置。

          Event_type代表事件的類型。

          Server_id是創(chuàng)建事件的服務(wù)器ID。

          End_log_pos代表事件在文件中的結(jié)束位置,以上面為例,第一次查詢的結(jié)束位置是723,第二次insert之后文件的開始位置就是從723開始。

          Info代表事件信息,是一段可讀的文本內(nèi)容。

          binlog日志結(jié)構(gòu)

          binlog日志的結(jié)構(gòu)大概是長這樣的,它由索引文件和binlog文件組成,其中binlog事件又包含通用頭、提交頭和事件體3個(gè)部分組成。

          首先說說索引文件,索引文件的每一行都包含了一個(gè)binlog文件的完整文件名(類似host-bin.001),一些命令比如flush logs將所有日志寫入磁盤會影響到索引文件。

          每個(gè)binlog文件以若干個(gè)binlog事件組成,以格式描述事件(Format_description)作為文件頭(上面的binlog圖片F(xiàn)ormat_desc事件),以日志輪換事件(rotate)作為文件尾。

          Format_description包含binlog文件的服務(wù)器信息、文件狀態(tài)的關(guān)鍵信息等。如果服務(wù)器關(guān)閉或者重啟,則會創(chuàng)建一個(gè)新的binlog文件,同時(shí)寫入一個(gè)新的format_description。他的格式大致如下。

          2????????????????binlog-version
          string[50]???????mysql-server?version
          4????????????????create?timestamp
          1????????????????event?header?length
          string[p]????????event?type?header?lengths

          日志輪換事件則包含下一個(gè)binlog的文件名以及開始讀取的位置,它由服務(wù)器寫完binlog后添加到文件尾,輪換事件并不會每次都存在,格式如下。

          if?binlog-version?>?1?{
          8??????????????position
          }
          string[p]??????name?of?the?next?binlog

          binlog事件包含若干個(gè)事務(wù)組成的組(group),每個(gè)組對應(yīng)一個(gè)事務(wù),如果是create alter語句不屬于事務(wù)語句的話,則他們本身就是一個(gè)組,每個(gè)組要么全部執(zhí)行,要么都不執(zhí)行。

          binlog事件結(jié)構(gòu)

          每個(gè)binlog事件由3個(gè)部分組成:

          1. 通用頭,包含binlog中所有事件具備的基本信息。
          2. 提交頭,對于不同類型的事件來說,提交頭的內(nèi)容也不盡相同
          3. 事件體,存儲事件的主要數(shù)據(jù),同樣對于不同類型事件也不同。

          binlog輪換和清理

          從上面的例子我們也可以看出來,binlog并非只有一個(gè),而基于真實(shí)的場景來說,始終寫一個(gè)binlog文件肯定也是不可取的,而binlog輪換主要有3個(gè)場景:

          1. 服務(wù)器啟動,每次服務(wù)器啟動都會生成一個(gè)新的binlog文件。
          2. 達(dá)到最大大小,可以通過binlog-cache-size控制大小,達(dá)到最大大小后將更換。
          3. 顯示刷新,flush logs將所有日志寫入磁盤,這時(shí)候會創(chuàng)建一個(gè)新的文件寫入,從第一個(gè)例子也能看出來執(zhí)行完之后生成了一個(gè)新的日志binlog.000030的文件并且開始的位置是4。

          隨著時(shí)間的推移,我們的binlog文件會越來越多,這時(shí)候有兩種方式可以清除binlog:

          1. 通過設(shè)置expire-logs-days控制想保留的binlog日志文件天數(shù),系統(tǒng)將會自動清理。
          2. 通過PURGE BINARY LOGS手動清理

          relay-log結(jié)構(gòu)

          relay-log中繼日志是連接master和slave的核心,我們來深入了解一下它的結(jié)構(gòu)和使用。

          image-20200909161115718

          relay-log的結(jié)構(gòu)和binlog非常相似,只不過他多了一個(gè)master.info和relay-log.info的文件。

          master.info記錄了上一次讀取到master同步過來的binlog的位置,以及連接master和啟動復(fù)制必須的所有信息。

          relay-log.info記錄了文件復(fù)制的進(jìn)度,下一個(gè)事件從什么位置開始,由sql線程負(fù)責(zé)更新。

          上一篇文章我們提到了整個(gè)復(fù)制流程的過程大概是這個(gè)樣子:

          知道binlog和relay-log的結(jié)構(gòu)之后,我們重新梳理一下整個(gè)鏈路的流程,這里我們假定master.info和relay-log.info都是存在的情況:

          1. Master收到客戶端請求語句,在語句結(jié)束之前向二進(jìn)制日志寫入一條記錄,可能包含多個(gè)事件。
          2. 此時(shí),一個(gè)Slave連接到Master,Master的dump線程從binlog讀取日志并發(fā)送到Slave的IO線程。
          3. IO線程從master.info讀取到上一次寫入的最后的位置。
          4. IO線程寫入日志到relay-log中繼日志,如果超過指定的relay-log大小,寫入輪換事件,創(chuàng)建一個(gè)新的relay-log。
          5. 更新master.info的最后位置
          6. SQL線程從relay-log.info讀取進(jìn)上一次讀取的位置
          7. SQL線程讀取日志事件
          8. 在數(shù)據(jù)庫中執(zhí)行sql
          9. 更新relay-log.info的最后位置
          10. Slave記錄自己的binlog日志

          但是在這里IO和SQL線程有會產(chǎn)生重復(fù)事件的問題,舉一個(gè)場景:

          1. 先記錄中繼日志,然后更新master.info位置
          2. 此時(shí)服務(wù)器崩潰,寫入master.info失敗
          3. 服務(wù)器恢復(fù),再次同步從master.info獲取到的是上一次的位置,會導(dǎo)致事件重復(fù)執(zhí)行

          既然會有這個(gè)問題還為什么要這樣做呢?假設(shè)反過來,先更新master.info再記錄中繼日志,這樣帶來的問題就是丟失數(shù)據(jù)了。而mysql認(rèn)為丟失比重復(fù)更嚴(yán)重,所以要先刷新日志,保大還是保小mysql幫你做了決定。

          推薦閱讀

          阿里精選:Java 代碼精簡之道

          Java8 中用法優(yōu)雅的 Stream,性能也""優(yōu)雅""嗎?

          ElasticSearch 索引 VS MySQL 索引

          還在手動部署SpringBoot應(yīng)用?試試這個(gè)自動化插件!

          MySQL執(zhí)行計(jì)劃Explain詳解

          瀏覽 60
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91视频在线观看 | 美女成人视频 | 亚洲色一区二区三区 | 五月丁香夫妻自拍偷拍 | 影音先锋在线成人视频 |