MySQL 中的 binlog 和 relay-log 結構完全詳解

2021-03-02 Python中文社區

今天我們來深挖一下mysql的複製機制到底有哪一些,以及binlog和relay-log的結構到底是什麼樣子的。

binlog作用

binlog的主要作用是記錄資料庫中表的更改,它只記錄改變數據的sql,不改變數據的sql不會寫入,比如select語句一般不會被記錄,因為他們不會對數據產生任何改動。

用一個實際的場景看下binlog產生的過程,準備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';

顯示的結果如下:

binlog

另外,也可以使用mysqlbinlog工具來查看binlog的內容:

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

從日誌我們可以看到執行了創建表的語句以及一個Format_desc頭和Ratate輪換事件,這個我們會在後面講到,先看幾個欄位代表的含義。

Log_name代表日誌文件的名稱,比如我這裡的查詢是直接查詢binlog.000029,默認的寫法是show binlog events,但是這樣只會查詢到第一個binlog,並不是當前激活狀態的binlog,如果你不知道binlog有哪些,可以用命令:

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

Pos代表文件開始的位置。

Event_type代表事件的類型。

Server_id是創建事件的伺服器ID。

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

Info代表事件信息,是一段可讀的文本內容。

binlog日誌結構

binlog日誌的結構大概是長這樣的,它由索引文件和binlog文件組成,其中binlog事件又包含通用頭、提交頭和事件體3個部分組成。

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

每個binlog文件以若干個binlog事件組成,以格式描述事件(Format_description)作為文件頭(上面的binlog圖片Format_desc事件),以日誌輪換事件(rotate)作為文件尾。

Format_description包含binlog文件的伺服器信息、文件狀態的關鍵信息等。如果伺服器關閉或者重啟,則會創建一個新的binlog文件,同時寫入一個新的format_description。他的格式大致如下。

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

日誌輪換事件則包含下一個binlog的文件名以及開始讀取的位置,它由伺服器寫完binlog後添加到文件尾,輪換事件並不會每次都存在,格式如下。

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

binlog事件包含若干個事務組成的組(group),每個組對應一個事務,如果是create alter語句不屬於事務語句的話,則他們本身就是一個組,每個組要麼全部執行,要麼都不執行。

binlog事件結構

每個binlog事件由3個部分組成:

通用頭,包含binlog中所有事件具備的基本信息。提交頭,對於不同類型的事件來說,提交頭的內容也不盡相同事件體,存儲事件的主要數據,同樣對於不同類型事件也不同。binlog輪換和清理

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

伺服器啟動,每次伺服器啟動都會生成一個新的binlog文件。達到最大大小,可以通過binlog-cache-size控制大小,達到最大大小後將更換。顯示刷新,flush logs將所有日誌寫入磁碟,這時候會創建一個新的文件寫入,從第一個例子也能看出來執行完之後生成了一個新的日誌binlog.000030的文件並且開始的位置是4。

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

通過設置expire-logs-days控制想保留的binlog日誌文件天數,系統將會自動清理。relay-log結構

relay-log中繼日誌是連接master和slave的核心,我們來深入了解一下它的結構和使用。

image-20200909161115718

relay-log的結構和binlog非常相似,只不過他多了一個master.info和relay-log.info的文件。

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

relay-log.info記錄了文件複製的進度,下一個事件從什麼位置開始,由sql線程負責更新。

上一篇文章我們提到了整個複製流程的過程大概是這個樣子:

知道binlog和relay-log的結構之後,我們重新梳理一下整個鏈路的流程,這裡我們假定master.info和relay-log.info都是存在的情況:

Master收到客戶端請求語句,在語句結束之前向二進位日誌寫入一條記錄,可能包含多個事件。此時,一個Slave連接到Master,Master的dump線程從binlog讀取日誌並發送到Slave的IO線程。IO線程從master.info讀取到上一次寫入的最後的位置。IO線程寫入日誌到relay-log中繼日誌,如果超過指定的relay-log大小,寫入輪換事件,創建一個新的relay-log。SQL線程從relay-log.info讀取進上一次讀取的位置

但是在這裡IO和SQL線程有會產生重複事件的問題,舉一個場景:

先記錄中繼日誌,然後更新master.info位置伺服器恢復,再次同步從master.info獲取到的是上一次的位置,會導致事件重複執行

既然會有這個問題還為什麼要這樣做呢?假設反過來,先更新master.info再記錄中繼日誌,這樣帶來的問題就是丟失數據了。而mysql認為丟失比重複更嚴重,所以要先刷新日誌,保大還是保小mysql幫你做了決定。

長按掃碼添加「Python小助手」

▼點擊成為社區會員   喜歡就點個在看吧

相關焦點

  • Mysql的binlog和relay-log到底長啥樣?
    上一篇mysql面試的文章之後收到不少朋友的意見,希望深入講講複製、日誌的格式這些,今天,我們就來深挖一下mysql的複製機制到底有哪一些,以及binlog和relay-log的結構到底是什麼樣子的。binlog日誌結構binlog日誌的結構大概是長這樣的,它由索引文件和binlog文件組成,其中binlog事件又包含通用頭、提交頭和事件體3個部分組成。
  • binlog和relay-log到底長啥樣?
    本文公眾號來源:科技繆繆今天,我們就來深挖一下mysql的複製機制到底有哪一些,以及binlog和relay-log的結構到底是什麼樣子的。binlog日誌結構binlog日誌的結構大概是長這樣的,它由索引文件和binlog文件組成,其中binlog事件又包含通用頭、提交頭和事件體3個部分組成。
  • 必須了解的mysql三大日誌-binlog、redo log和undo log
    日誌是 mysql 資料庫的重要組成部分,記錄著資料庫運行期間各種狀態信息。mysql日誌主要包括錯誤日誌、查詢日誌、慢查詢日誌、事務日誌、二進位日誌幾大類。作為開發,我們重點需要關注的是二進位日誌( binlog )和事務日誌(包括redo log 和 undo log ),本文接下來會詳細介紹這三種日誌。
  • 必須了解的MySQL三大日誌:binlog、redo log和undo log
    日誌是mysql資料庫的重要組成部分,記錄著資料庫運行期間各種狀態信息。mysql日誌主要包括錯誤日誌、查詢日誌、慢查詢日誌、事務日誌、二進位日誌幾大類。作為開發,我們重點需要關注的是二進位日誌(binlog)和事務日誌(包括redo log和undo log),本文接下來會詳細介紹這三種日誌。
  • 用 Docker 構建 MySQL 主從環境
    MySQL 主從同步分為 5 個步驟:1.master 節點將數據的更新記錄寫到 binary log 中。2.slave 節點開啟 IO 線程連接 master 節點,請求獲取指定 binary log 文件的指定位置之後的日誌。3.master 節點的 binary log dump 線程將指定的 binary log 信息推送給 slave 節點。4.slave 節點的 IO 線程接收到消息後,將日誌內容寫入 relay log 文件。
  • 淺析 MySQL Replication
    relay-log 中繼日誌文件,slave 的I/O線程讀取 master 的 binlog,記錄到 relay-log 中,然後 SQL 線程會讀取 relay-log 日誌的內容並應用到 slave 伺服器。
  • 【用binlog日誌】恢復 MySQL 資料庫刪除數據
    binlog 就是binary log,二進位日誌文件,這個文件記錄了MySQL所有的DDL和DML(除了數據查詢語句)語句,以事件形式記錄,還包含語句所執行的消耗的時間。cat more vi等都無法打開,必須使用自帶的 mysqlbinlog 命令查看binlog日誌與資料庫文件在同目錄中。
  • 【140期】MySQL中的redolog,undolog,以及binlog的區別及各自作用是什麼?
    ,分別是:重做日誌(redo log)、回滾日誌(undo log)、二進位日誌(binlog)、錯誤日誌(errorlog)、慢查詢日誌(slow query log)、一般查詢日誌(general log),中繼日誌(relay log)。
  • 終於學會了 MySQL 主從配置和讀寫分離
    I/O線程: 此線程連接到主節點,主節點上的 binlog dump 線程會將 binlog 的內容發送給此線程。此線程接收到 binlog 內容後,再將內容寫入到本地的 relay log。='mysql-bin.000001' ,master_log_pos=154;其中 master_host表示主伺服器 IP,master_user和master_password分別是主伺服器的用戶名和密碼,master_log_file和master_log_pos在主伺服器中通過show master status語句可以查到。
  • MySQL - binlog日誌簡介及設置
    MySQL binlog格式binlog的格式也有三種:STATEMENT、ROW、MIXED 。1、STATMENT模式:基於SQL語句的複製(statement-based replication, SBR),每一條會修改數據的sql語句會記錄到binlog中。
  • 面試被問MySQL 主從複製,怎麼破?
    log)-- 從庫 I/O 線程;從庫讀取中繼日誌中的事件,將其重放到數據中 -- 從庫 SQL 線程。># 3.2 修改配置文件1)vim /etc/my.cnf 在[mysqld]下添加:log-bin         = mysql-binlog-bin-index   = mysql-bin.indexbinlog_format   = mixedserver-id       = 21sync-binlog
  • 深入理解MySQL 5.7 GTID系列(六):MySQL啟動初始化GTID模塊
    = LOG_INFO_EOF)  {    DBUG_PRINT("error", ("Error reading %s index",                         is_relay_log ? "relaylog" : "binlog"));    goto end;  } if (all_gtids !
  • MySQL 5.7基於GTID及多線程主從複製
    MySQL中主從複製的優點橫向擴展解決方案在多個從庫之間擴展負載以提高性能。在這種環境中,所有寫入和更新在主庫上進行。但是,讀取可能發生在一個或多個從庫上。該模型可以提高寫入的性能(由於主庫專用於更新),同時在多個從庫上讀取,可以大大提高讀取速度。
  • MySQL基於MHA的FailOver過程
    到各個節點,恢復情況二:ssh法連接調用 apply_diff_relay_logs 腳本,計算從庫的relaylog差異,恢復到2號從庫提供額外的數據補償功能解除從庫身份剩餘從庫和主庫構建主從關係:新機器接收的二進位日誌存放位置vim /etc/mha/app1.cnf [binlog1] no_master=1 hostname=192.168.255.116 master_binlog_dir=/data/mysql/binlog
  • 高性能Mysql主從架構的複製原理及配置詳解
    ,binary log events);slave將master的binary log events拷貝到它的中繼日誌(relay log);slave重做中繼日誌中的事件,將改變反映它自己的數據。用戶名的密碼都會存儲在文本文件master.info中命令如下:建立一個帳戶backup,並且只能允許從10.100.0.200這個地址上來登陸,密碼是1234。如果因為mysql版本新舊密碼算法不同,可以設置:拷貝數據:(假如是你完全新安裝mysql主從伺服器,這個一步就不需要。
  • MySQL主從複製高級進階
    延時從庫介紹及配置SQL線程延時:數據已經寫入relaylog中了,SQL線程稍後執行。所以如果從庫原本已經是延遲從庫了,需要重新設置延遲數值時,重啟從庫複製以後,會發現原有的relay log被清空了,並重新生成了序號從1開始的relay log。但不用擔心複製會被影響,因重新生成的relay log,是根據上一次從庫停止時所應用到的主庫log pos重新從主庫拉取binlog的。
  • MySQL Group Replication 學習筆記
    對於非執行事務的遠程節點,如果事務判斷為執行成功,遠程發送過來的數據,會被保存在本地的一個relay log裡面(注意,與常規主從同步使用的relay log不是同一組),之後由從庫的applier線程採用正常主從同步(目前已經支持LOGICAL_CLOCK並行執行)的方式執行掉對應的relay log。
  • MySQL Binlog 文件格式解析二(GTID_LOG_EVENT)
    關於MySQL Binlog以及event的基本結構,可以翻閱之前的文章。什麼是GTID_LOG_EVENT?插入一條記錄,看下這個sql在binlog裡由哪幾個部分組成。insert into tb values(1);解析binlog,執行:show binlog events in 'mysql-bin.000001';可以看到一條插入語句,在binlog中變成了多個event。
  • MySQL 日誌(redo log 和 undo log) 都是什麼鬼?
    在主從複製結構中,要保證事務的持久性和一致性,需要對日誌相關變量設置為如下:如果啟用了二進位日誌,則設置sync_binlog=1,即每提交一次事務同步寫到磁碟中。總是設置innodb_flush_log_at_trx_commit=1,即每提交一次事務都寫到磁碟中。
  • 問題定位 | Peronca Xtrabackup 8.0近日踩坑總結 - xtrabackup 2.4和8.0區別
    log_status 表通知在線備份工具當前主庫的 binlog 的位點和 gtid_executed 的值以及每個複製通道的 relay log。另外,它還提供了各個存儲引擎的相關信息,比如,提供了 InnoDB 引擎使用的最後一個日誌序列號(LSN)和最後一個檢查點的 LSN。