mysqlbinlog 使用詳解(附應用例項 恢復資料 日常維護)
阿新 • • 發佈:2022-05-15
Mysql binlog使用詳解
(1)MySQL主從複製:MySQL Replication在Master端開啟binlog,Master把它的二進位制日誌傳遞給slaves來達到master-slave資料一致的目的
(2)資料恢復:通過使用 mysqlbinlog工具來使恢復資料。
基於行的複製,不記錄每一條SQL語句的上下文資訊,僅記錄哪條資料被修改了,修改後的結果是什麼。
優點:不會出現某些特定情況下的儲存過程、或function、或trigger的呼叫和觸發無法被正確複製的問題。
缺點:會產生大量的日誌,尤其是alter table的時候會讓日誌暴漲。
在磁碟和網路允許的情況下,可以使用row模式,畢竟他準確率比較高。如果使用1和3,有可能出現不一致的情況。比如
當在master上更新一條從庫不存在的記錄時,也就是id=2的記錄,你會發現master是可以執行成功的。而slave拿到這個SQL後,也會照常執行,不報任何異常,只是更新操作不影響行數而已。並且你執行命令show slave status,檢視輸出,你會發現沒有異常。但是,如果你是row模式,由於這行根本不存在,是會報1062錯誤的。
一、mysql常見日誌。
可根據具體需求,對不同的日誌進行分析。日誌型別 | 作用 |
錯誤日誌 | 記錄在啟動,執行或停止mysqld時遇到的問題 |
通用查詢日誌 | 記錄建立的客戶端連線和執行的語句 |
二進位制日誌 | 記錄更改資料的語句 |
中繼日誌 | 從複製主伺服器接收的資料更改 |
慢查詢日誌 | 記錄所有執行時間超過 long_query_time 秒的所有查詢或不使用索引的查詢 |
DDL日誌(元資料日誌) | 元資料操作由DDL語句執行 |
二、binlog的作用及應用場景。
1、作用:
MySQL 的二進位制日誌 binlog 可以說是 MySQL 最重要的日誌,它記錄了所有的 DDL 和 DML 語句(除了資料查詢語句select、show等),以事件形式記錄,還包含語句所執行的消耗的時間,MySQL的二進位制日誌是事務安全型的。binlog 的主要目的是複製和恢復。2、應用場景:
三、binlog三種模式及特點。
binlog主要包括statement、row、mixed三種模式。1、STATMENT模式(儲存為sql語句)
基於SQL語句的複製,每一條會修改資料的sql語句會記錄到binlog中。 優點:不需要記錄每一條SQL語句與每行的資料變化,這樣子binlog的日誌也會比較少,減少了磁碟IO,提高效能。 缺點:在某些情況下會導致master-slave(主從複製模式)中的資料不一致(如sleep(暫停指定時間執行)函式, last_insert_id(自增)等情況下會出現問題)2、ROW模式(儲存每行資料的變化記錄)
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、使用建議
四、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
事件型別 | 說明 |
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.sql2、使用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.htm3、常見mysqlbinlog工具比對。
canal、maxwell、databus、阿里dts 引用自:https://www.jb51.net/article/208508.htmCanal
定位:基於資料庫增量日誌解析,提供增量資料訂閱&消費,目前主要支援了mysql。 原理:- canal模擬mysql slave的互動協議,偽裝自己為mysql slave,向mysql master傳送dump協議
- mysql master收到dump請求,開始推送binary log給slave(也就是canal)
- canal解析binary log物件(原始為byte流)
- 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提供以下功能:- 源與消費者之間的隔離
- 保證按順序和至少一次交付具有高可用性
- 從更改流中的任意時間點開始消耗,包括整個資料的完全引導功能。
- 分割槽消費
- 源一致性儲存