1. 程式人生 > 其它 >mysqlbinlog 使用詳解(附應用例項 恢復資料 日常維護)

mysqlbinlog 使用詳解(附應用例項 恢復資料 日常維護)

  Mysql binlog使用詳解

一、mysql常見日誌。

可根據具體需求,對不同的日誌進行分析。
日誌型別 作用
錯誤日誌 記錄在啟動,執行或停止mysqld時遇到的問題
通用查詢日誌 記錄建立的客戶端連線和執行的語句
二進位制日誌 記錄更改資料的語句
中繼日誌 從複製主伺服器接收的資料更改
慢查詢日誌 記錄所有執行時間超過 long_query_time 秒的所有查詢或不使用索引的查詢
DDL日誌(元資料日誌) 元資料操作由DDL語句執行

二、binlog的作用及應用場景。

1、作用:
MySQL 的二進位制日誌 binlog 可以說是 MySQL 最重要的日誌,它記錄了所有的 DDL 和 DML 語句(除了資料查詢語句select、show等),以事件形式記錄,還包含語句所執行的消耗的時間,MySQL的二進位制日誌是事務安全型的。binlog 的主要目的是複製和恢復。
2、應用場景:
(1)MySQL主從複製:MySQL Replication在Master端開啟binlog,Master把它的二進位制日誌傳遞給slaves來達到master-slave資料一致的目的 (2)資料恢復:通過使用 mysqlbinlog工具來使恢復資料。  

三、binlog三種模式及特點。

binlog主要包括statement、row、mixed三種模式。
1、STATMENT模式(儲存為sql語句)
基於SQL語句的複製,每一條會修改資料的sql語句會記錄到binlog中。 優點:不需要記錄每一條SQL語句與每行的資料變化,這樣子binlog的日誌也會比較少,減少了磁碟IO,提高效能。 缺點:在某些情況下會導致master-slave(主從複製模式)中的資料不一致(如sleep(暫停指定時間執行)函式, last_insert_id(自增)等情況下會出現問題)
2、ROW模式(儲存每行資料的變化記錄)
基於行的複製,不記錄每一條SQL語句的上下文資訊,僅記錄哪條資料被修改了,修改後的結果是什麼。 優點:不會出現某些特定情況下的儲存過程、或function、或trigger的呼叫和觸發無法被正確複製的問題。 缺點:會產生大量的日誌,尤其是alter table的時候會讓日誌暴漲。
3、MIXED模式(自動判斷,混合使用)
混合模式的複製方式:如上兩種模式的混合使用,一般的複製使用STATEMENT模式儲存binlog,對於STATEMENT模式無法複製的相關操作使用ROW模式儲存binlog,MySQL會根據執行的SQL語句選擇日誌儲存方式。也有可能發生主從不一致的情況。 在 MySQL 5.7.7 之前,預設的格式是 STATEMENT,在 MySQL 5.7.7 及更高版本中,預設值是 ROW。日誌格式通過 binlog-format 指定,如 binlog-format=STATEMENT、binlog-format=ROW、binlog-format=MIXED。  
4、使用建議
在磁碟和網路允許的情況下,可以使用row模式,畢竟他準確率比較高。如果使用1和3,有可能出現不一致的情況。比如 當在master上更新一條從庫不存在的記錄時,也就是id=2的記錄,你會發現master是可以執行成功的。而slave拿到這個SQL後,也會照常執行,不報任何異常,只是更新操作不影響行數而已。並且你執行命令show slave status,檢視輸出,你會發現沒有異常。但是,如果你是row模式,由於這行根本不存在,是會報1062錯誤的。

四、binlog常見操作

1、啟用binlog。
開啟binlog一般會有1%左右的效能損耗。可通過一下兩種方式進行開啟。 #第一種方式: #開啟binlog日誌 log_bin=ON #binlog日誌的基本檔名 log_bin_basename=/var/lib/mysql/mysql-bin #binlog檔案的索引檔案,管理所有binlog檔案 log_bin_index=/var/lib/mysql/mysql-bin.index #配置serverid server-id=1   #第二種方式: #此一行等同於上面log_bin三行 log-bin=/var/lib/mysql/mysql-bin #配置serverid server-id=1   啟用後檢視是否成功。執行show variables like '%log_bin%'; 看到下圖即可。  
2、binlog配置項。
[mysqld] #設定日誌三種格式:STATEMENT、ROW、MIXED 。 binlog_format = mixed #設定日誌路徑,注意路經需要mysql使用者有許可權寫 log-bin = /data/mysql/logs/mysql-bin.log #設定binlog清理時間 expire_logs_days = 7 #binlog每個日誌檔案大小 max_binlog_size = 100m #binlog快取大小 binlog_cache_size = 4m #最大binlog快取大小 max_binlog_cache_size = 512m   修改配置後重啟mysql生效。  
3、常用命令。
是否啟用binlog日誌 show variables like 'log_bin'; 檢視詳細的日誌配置資訊 show global variables like '%log%'; mysql資料儲存目錄 show variables like '%dir%'; 檢視binlog的目錄 show global variables like "%log_bin%"; 檢視當前伺服器使用的binlog檔案及大小 show binary logs; 檢視主伺服器使用的biglog檔案及大小 檢視最新一個binlog日誌檔名稱和Position show master status; 事件查詢命令 IN 'log_name' :指定要查詢的binlog檔名(不指定就是第一個binlog檔案) FROM pos :指定從哪個pos起始點開始查起(不指定就是從整個檔案首個pos點開始算) LIMIT [offset,] :偏移量(不指定就是0) row_count :查詢總條數(不指定就是所有行) show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]; 檢視 binlog 內容 show binlog events; 檢視具體一個binlog檔案的內容 (in 後面為binlog的檔名) show binlog events in 'master.000003'; 設定binlog檔案儲存事件,過期刪除,單位天 set global expire_log_days=3; 刪除當前的binlog檔案 reset master; 刪除slave的中繼日誌 reset slave; 刪除指定日期前的日誌索引中binlog日誌檔案 purge master logs before '2019-03-09 14:00:00'; 刪除指定日誌檔案 purge master logs to 'master.000003';  
4、binlog生成時機。
對支援事務的引擎如InnoDB而言,必須要提交了事務才會記錄binlog。binlog 什麼時候重新整理到磁碟跟引數 sync_binlog 相關。 在MySQL 5.7.7之前,預設值 sync_binlog 是0,MySQL 5.7.7和更高版本使用預設值1,這是最安全的選擇。一般情況下會設定為100或者0,犧牲一定的一致性來獲取更好的效能。 引數sync_binlog=[N]表示每寫緩衝多次就同步到磁碟,設定為1,表示寫入binlog的同時也寫入磁碟,這種情況最安全,速度也最慢(mysql5.7後這是預設選項)。緩衝的次數越多,有可能丟的資料越多,但是效能越好。設定為0表示mysql不控制,由檔案系統控制快取的重新整理。  
5、檢視分析binlog。
(1)命令列使用 show binlog events。
show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]; a、命令引數解釋: log_name:可以指定要檢視的 binlog 日誌檔名,如果不指定的話,表示檢視最早的 binlog 檔案。 pos:從哪個 pos 點開始檢視,凡是 binlog 記錄下來的操作都有一個 pos 點,這個其實就是相當於我們可以指定從哪個操作開始檢視日誌,如果不指定的話,就是從該 binlog 的開頭開始檢視。 offset:這是是偏移量,不指定預設就是 0。 row_count:檢視多少行記錄,不指定就是檢視所有。 b、舉例1: show binlog events in 'javaboy_logbin.000001'; 下圖是row格式的binlog。 c、舉例2: binlog event分析 如果binlog格式設定為statement,會儲存create、insert、update、delete等事件,結果如下: 如果binlog格式設定為row,會儲存create、insert、update、delete等事件,結果如下: 這裡如果要看具體的sql語句, 需要用mysqlbinlog 加上-v引數,會將row格式內容解析為sql。  
(2)linux命令列使用mysqlbinlog。
a、基本格式: mysqlbinlog [options] log_file ... 檢視bin-log二進位制檔案(shell方式): mysqlbinlog -v --base64-output=decode-rows /var/lib/mysql/master.00000 檢視bin-log二進位制檔案(帶查詢條件): mysqlbinlog -v --base64-output=decode-rows /var/lib/mysql/master.000003 \ --start-datetime="2019-03-01 00:00:00" \ --stop-datetime="2019-03-10 00:00:00" \ --start-position="5000" \ --stop-position="20000" b、mysqlbinlog遠端匯出 mysqlbinlog -u username -p password -hl-db1.dba.beta.cn6.qunar.com -P3306 \ --read-from-remote-server --start-datetime='2013-09-10 23:00:00' --stop-datetime='2013-09-10 23:30:00' mysql-bin.000001 > t.binlog c、舉例:擷取一段mysqlbinlog 輸出的資訊如下。 ==================================================================== # at 21019 #190308 10:10:09 server id 1 end_log_pos 21094 CRC32 0x7a405abc Query thread_id=113 exec_time=0 error_code=0 SET TIMESTAMP=1552011009/*!*/; BEGIN /*!*/; ==================================================================== 上面輸出包括資訊:
  • position: 位於檔案中的位置,即第一行的(# at 21019),說明該事件記錄從檔案第21019個位元組開始
  • timestamp: 事件發生的時間戳,即第二行的(#190308 10:10:09)
  • server id: 伺服器標識(1)
  • end_log_pos 表示下一個事件開始的位置(即當前事件的結束位置+1)
  • thread_id: 執行該事件的執行緒id (thread_id=113)
  • exec_time: 事件執行的花費時間
  • error_code: 錯誤碼,0意味著沒有發生錯誤
  • type:事件型別Query
c、binlog常見事件型別解釋。
事件型別 說明
UNKNOWN_EVENT 此事件從不會被觸發,也不會被寫入binlog中;發生在當讀取binlog時,不能被識別其他任何事件,那被視為UNKNOWN_EVENT
START_EVENT_V3 每個binlog檔案開始的時候寫入的事件,此事件被用在MySQL3.23 – 4.1,MYSQL5.0以後已經被 FORMAT_DESCRIPTION_EVENT 取代
QUERY_EVENT 執行更新語句時會生成此事件,包括:create,insert,update,delete;
STOP_EVENT 當mysqld停止時生成此事件
ROTATE_EVENT 當mysqld切換到新的binlog檔案生成此事件,切換到新的binlog檔案可以通過執行flush logs命令或者binlog檔案大於 max_binlog_size 引數配置的大小;
INTVAR_EVENT 當sql語句中使用了AUTO_INCREMENT的欄位或者LAST_INSERT_ID()函式;此事件沒有被用在binlog_format為ROW模式的情況下
LOAD_EVENT 執行LOAD DATA INFILE 語句時產生此事件,在MySQL 3.23版本中使用
SLAVE_EVENT 未使用
CREATE_FILE_EVENT 執行LOAD DATA INFILE 語句時產生此事件,在MySQL4.0和4.1版本中使用
APPEND_BLOCK_EVENT 執行LOAD DATA INFILE 語句時產生此事件,在MySQL4.0版本中使用
EXEC_LOAD_EVENT 執行LOAD DATA INFILE 語句時產生此事件,在MySQL4.0和4.1版本中使用
DELETE_FILE_EVENT 執行LOAD DATA INFILE 語句時產生此事件,在MySQL4.0版本中使用
NEW_LOAD_EVENT 執行LOAD DATA INFILE 語句時產生此事件,在MySQL4.0和4.1版本中使用
RAND_EVENT 執行包含RAND()函式的語句產生此事件,此事件沒有被用在binlog_format為ROW模式的情況下
USER_VAR_EVENT 執行包含了使用者變數的語句產生此事件,此事件沒有被用在binlog_format為ROW模式的情況下
FORMAT_DESCRIPTION_EVENT 描述事件,被寫在每個binlog檔案的開始位置,用在MySQL5.0以後的版本中,代替了START_EVENT_V3
XID_EVENT 支援XA的儲存引擎才有,本地測試的資料庫儲存引擎是innodb,所有上面出現了XID_EVENT;innodb事務提交產生了QUERY_EVENT的BEGIN宣告,QUERY_EVENT以及COMMIT宣告,如果是myIsam儲存引擎也會有BEGIN和COMMIT宣告,只是COMMIT型別不是XID_EVENT
BEGIN_LOAD_QUERY_EVENT 執行LOAD DATA INFILE 語句時產生此事件,在MySQL5.0版本中使用
EXECUTE_LOAD_QUERY_EVENT 執行LOAD DATA INFILE 語句時產生此事件,在MySQL5.0版本中使用
TABLE_MAP_EVENT 用在binlog_format為ROW模式下,將表的定義對映到一個數字,在行操作事件之前記錄(包括:WRITE_ROWS_EVENT,UPDATE_ROWS_EVENT,DELETE_ROWS_EVENT)
PRE_GA_WRITE_ROWS_EVENT 已過期,被 WRITE_ROWS_EVENT 代替
PRE_GA_UPDATE_ROWS_EVENT 已過期,被 UPDATE_ROWS_EVENT 代替
PRE_GA_DELETE_ROWS_EVENT 已過期,被 DELETE_ROWS_EVENT 代替
WRITE_ROWS_EVENT 用在binlog_format為ROW模式下,對應 insert 操作
UPDATE_ROWS_EVENT 用在binlog_format為ROW模式下,對應 update 操作
DELETE_ROWS_EVENT 用在binlog_format為ROW模式下,對應 delete 操作
INCIDENT_EVENT 主伺服器發生了不正常的事件,通知從伺服器並告知可能會導致資料處於不一致的狀態
HEARTBEAT_LOG_EVENT 主伺服器告訴從伺服器,主伺服器還活著,不寫入到日誌檔案中
(3)使用第三方分析工具binlog2sql
官方倉庫:https://github.com/danfengcao/binlog2sql 快速上手: a、安裝依賴。 git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql pip install -r requirements.txt b、使用(如果不提供偏移位置或者起始時間,就從頭開始顯示所有資訊) # 使用偏移位置 python binlog2sql.py -h127.0.0.1 -P3306 -uroot -p'root' --start-file='mysqld-bin.000001' --start-pos=2425 -d aaaa # 同樣功能,使用時間戳 python binlog2sql.py -h127.0.0.1 -P3306 -uroot -p'root' --start-file='mysqld-bin.000001' --start-datetime='2018-08-02 10:00:00' -d aaaa c、結果示例 USE aaaa; -- 建表 create table aaa(id int, title varchar(100)); USE aaaa; -- 插入初始化資料 insert into aaa(id, title) values (1, '測試1'); USE aaaa; insert into aaa(id, title) values (2, '測試2'); USE aaaa; insert into aaa(id, title) values (3, '測試3'); USE aaaa; -- 更新/刪除 update aaa set title='修改' where id=2; USE aaaa; delete from aaa where id=1;  

五、應用例項。

1、使用mysqlbinlog檢視sql執行歷史。
(1)檢視mysql是否開啟binlog以及binlog檔案的儲存路徑。 show variables like 'log_bin'; 如果沒開啟就該配置檔案進行開啟。 (2)檢視binlog檔名。 show master status; (3)進入到當前主機的mysqlbinlog安裝目錄。 find / -name "mysqlbinlog" 進入上述路徑,然後儲存binlog為文字,然後下載用文字分析。 ./mysqlbinlog ./usr/local/mysql/data/mysql-bin.000007 -v /a.txt (4)也可以直接在命令列進行分析,舉例。 查詢時間段內日誌的執行內容 mysqlbinlog --start-datetime='2018-01-08 02:01:00' --stop-datetime='2018-01-08 02:30:10' -d test /var/lib/mysql/mysql-bin.000170 -v 查詢時間段內日誌中執行的刪除語句 mysqlbinlog --start-datetime='2018-01-08 02:01:00' --stop-datetime='2018-01-08 02:30:10' -d test /var/lib/mysql/mysql-bin.000170 -v|grep DELETE -A 5 統計時間段內日誌中執行的刪除語句 mysqlbinlog --start-datetime='2018-01-08 02:01:00' --stop-datetime='2018-01-08 02:30:10' -d test /var/lib/mysql/mysql-bin.000170 -v|grep DELETE |wc -l -v引數:重新構建偽SQL語句的行資訊輸出,-v -v會增加列型別的註釋資訊。如果檢視insert語句,直接使用mysqlbinlog過濾,看不到具體insert的值,只能看到insert語句。 (5)將binlog匯出為sql(具體使用百度mysqlbinlog 引數) mysqlbinlog --no-defaults --database=db --base64-output=decode-rows -v --start-datetime='2018-01-08 02:01:00' --stop-datetime='2018-01-08 02:30:10' mysql-bin.000170 /tmp/binlog007.sql  
2、使用binlog恢復資料庫。
最核心的一句:實際是將讀出的binlog日誌內容,通過管道符傳遞給mysql命令 mysqlbinlog –no-defaults –stop-datetime='2017-04-11 09:48:48'/data/mysql/mysql-bin.000001 |mysql –uroot –p123456 參考如下連結: https://www.jb51.net/article/236583.htm https://www.jb51.net/article/109588.htm https://www.jb51.net/article/236600.htm  
3、常見mysqlbinlog工具比對。
canal、maxwell、databus、阿里dts 引用自:https://www.jb51.net/article/208508.htm
Canal
定位:基於資料庫增量日誌解析,提供增量資料訂閱&消費,目前主要支援了mysql。 原理:
  • canal模擬mysql slave的互動協議,偽裝自己為mysql slave,向mysql master傳送dump協議
  • mysql master收到dump請求,開始推送binary log給slave(也就是canal)
  • canal解析binary log物件(原始為byte流)
整個parser過程大致可分為幾步:
  • Connection獲取上一次解析成功的位置(如果第一次啟動,則獲取初始制定的位置或者是當前資料庫的binlog位點)
  • Connection建立連線,發生BINLOG_DUMP命令
  • Mysql開始推送Binary Log
  • 接收到的Binary Log通過Binlog parser進行協議解析,補充一些特定資訊
  • 傳遞給EventSink模組進行資料儲存,是一個阻塞操作,直到儲存成功
  • 儲存成功後,定時記錄Binary Log位置
  • 資料過濾:支援萬用字元的過濾模式,表名,欄位內容等
  • 資料路由/分發:解決1:n (1個parser對應多個store的模式)
  • 資料歸併:解決n:1 (多個parser對應1個store)
  • 資料加工:在進入store之前進行額外的處理,比如join
 
Maxwell
canal 由Java開發,分為服務端和客戶端,擁有眾多的衍生應用,效能穩定,功能強大;canal 需要自己編寫客戶端來消費canal解析到的資料。 maxwell相對於canal的優勢是使用簡單,它直接將資料變更輸出為json字串,不需要再編寫客戶端。  
Databus
Databus是一種低延遲變化捕獲系統,已成為LinkedIn資料處理管道不可或缺的一部分。Databus解決了可靠捕獲,流動和處理主要資料更改的基本要求。Databus提供以下功能:
  • 源與消費者之間的隔離
  • 保證按順序和至少一次交付具有高可用性
  • 從更改流中的任意時間點開始消耗,包括整個資料的完全引導功能。
  • 分割槽消費
  • 源一致性儲存
 
阿里雲的資料傳輸服務DTS
資料傳輸服務(Data Transmission Service,簡稱DTS)是阿里雲提供的一種支援 RDBMS(關係型資料庫)、NoSQL、OLAP 等多種資料來源之間資料互動的資料流服務。DTS提供了資料遷移、實時資料訂閱及資料實時同步等多種資料傳輸能力,可實現不停服資料遷移、資料異地災備、異地多活(單元化)、跨境資料同步、實時資料倉庫、查詢報表分流、快取更新、非同步訊息通知等多種業務應用場景,助您構建高安全、可擴充套件、高可用的資料架構。 優勢:資料傳輸(Data Transmission)服務 DTS 支援 RDBMS、NoSQL、OLAP 等多種資料來源間的資料傳輸。它提供了資料遷移、實時資料訂閱及資料實時同步等多種資料傳輸方式。相對於第三方資料流工具,資料傳輸服務 DTS 提供更豐富多樣、高效能、高安全可靠的傳輸鏈路,同時它提供了諸多便利功能,極大得方便了傳輸鏈路的建立及管理。 個人理解:就是一個訊息佇列,會給你推送它包裝過的sql物件,可以自己做個服務去解析這些sql物件。 免去部署維護的昂貴使用成本。DTS針對阿里雲RDS(線上關係型資料庫)、DRDS等產品進行了適配,解決了Binlog日誌回收,主備切換、VPC網路切換等場景下的訂閱高可用問題。同時,針對RDS進行了針對性的效能優化。出於穩定性、效能及成本的考慮,推薦使用。 https://www.jb51.net/article/208508.htm  
4、正確清理binlog
(1)手動清理
a、檢視主庫和從庫正在使用哪個binlog。 show master status show slave status b、備份binlog,防止誤刪。 c、執行刪除操作(時間和檔名不要寫錯,不要刪除正在使用的binlog)。 purge master logs before'2016-09-01 17:20:00'; //刪除指定日期以前的日誌索引中binlog日誌檔案 purge master logs to'mysql-bin.000022'; //刪除指定日誌檔案的日誌索引中binlog日誌檔案
(2)自動清理
設定過期時間,系統自動刪除binlog show variables like 'expire_logs_days'; set global expire_logs_days = 30; #設定binlog多少天過期