一、什么是二進制日志
二進制日志主要記錄mysql數據庫的變化,二進制日志包含所有更新了數據或者潛在更新了數據(如沒有匹配到任何行的delete語句),語句以時間的形式保存,描述了數據的更改。二進制日志還包含執行每個更新數據庫語句的時間信息,使用二進制日志的主要目的是最大可能的恢復數據庫。因為二進制日志包含備份后進行的所有更新,不記錄沒有修改任何數據的語句。
開啟二進制日志對性能的開銷很小,帶來的好處遠大於壞處
二、開啟和設置二進制日志
1、默認情況下二進制日志是關閉的,通過配置文件來啟動和設置二進制日志。修改my.cng,插入如下內容,然后重啟mysqld服務。
server-id = 1 # mysql5.7必須加,否則mysql服務啟動報錯 log-bin = /data/3306/tmp/binlog/mysql-bin # 路徑及命名,默認在data下 expire_logs_days = 10 # 過期時間,二進制文件自動刪除的天數,0代表不刪除 max_binlog_size = 100M # 單個日志文件大小
2、通過show variables like 'log_bin%'查看二進制日志設置
mysql> show variables like 'log_bin%'; +---------------------------------+---------------------------------------+ | Variable_name | Value | +---------------------------------+---------------------------------------+ | log_bin | ON | | log_bin_basename | /data/3306/tmp/binlog/mysql-bin | | log_bin_index | /data/3306/tmp/binlog/mysql-bin.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | +---------------------------------+---------------------------------------+
3、查看當前服務器所有的二進制日志文件 show binary logs / show master logs
mysql> show binary logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 732 | +------------------+-----------+
4、查看當前二進制日志狀態 show master status
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 732 | | | | +------------------+----------+--------------+------------------+-------------------+
三、二進制日志切換方法
每次重啟MySQL服務也會生成一個新的二進制日志文件,相當於二進制日志切換。切換二進制日志時,你會看到這些number會不斷遞增。另外,除了這些二進制日志文件外,你會看到還生成了一個DB-Server-bin.index的文件,這個文件中存儲所有二進制日志文件的清單又稱為二進制文件的索引。
執行 flush logs 可以刷新切換二進制文件
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 732 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) mysql> flush logs; Query OK, 0 rows affected (0.00 sec) mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000002 | 154 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
四、二進制文件的查看
1、使用show binlog events 可以獲取當前及指定日志 show binlog events 'mysql-bin.000002' from 639(只產看639)
mysql> show binlog events; +------------------+-----+----------------+-----------+-------------+---------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+----------------+-----------+-------------+---------------------------------------+ | mysql-bin.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.24-log, Binlog ver: 4 | | mysql-bin.000001 | 123 | Previous_gtids | 1 | 154 | | | mysql-bin.000001 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | mysql-bin.000001 | 219 | Query | 1 | 291 | BEGIN | | mysql-bin.000001 | 291 | Table_map | 1 | 350 | table_id: 108 (test.t_count) | | mysql-bin.000001 | 350 | Write_rows | 1 | 412 | table_id: 108 flags: STMT_END_F | | mysql-bin.000001 | 412 | Xid | 1 | 443 | COMMIT /* xid=5 */ | | mysql-bin.000001 | 443 | Anonymous_Gtid | 1 | 508 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | mysql-bin.000001 | 508 | Query | 1 | 580 | BEGIN | | mysql-bin.000001 | 580 | Table_map | 1 | 639 | table_id: 108 (test.t_count) | | mysql-bin.000001 | 639 | Write_rows | 1 | 701 | table_id: 108 flags: STMT_END_F | | mysql-bin.000001 | 701 | Xid | 1 | 732 | COMMIT /* xid=7 */ | | mysql-bin.000001 | 732 | Rotate | 1 | 779 | mysql-bin.000002;pos=4 | +------------------+-----+----------------+-----------+-------------+---------------------------------------+
2、打印二進制日志到一個明文文件,該文件記錄的更新了數據的sql,但是在5.7以上已經被加密
mysqlbinlog /data/3306/tmp/binlog/mysql-bin.000001 > mysql-bin.log # 打印日志文件 mysqlbinlog --base64-output=decode-rows -v /data/3306/tmp/binlog/mysql-bin.000001 > binlog.sql # 解密文件
# 截取的部分日志內容,可以看到insert語句
BEGIN /*!*/; # at 580 #181215 11:12:03 server id 1 end_log_pos 639 CRC32 0xc66c75c3 Table_map: `test`.`t_count` mapped to number 108 # at 639 #181215 11:12:03 server id 1 end_log_pos 701 CRC32 0xf8a50341 Write_rows: table id 108 flags: STMT_END_F ### INSERT INTO `test`.`t_count` ### SET ### @1=533500356 ### @2='W3V' ### @3='fg8rVMuT0' ### @4='2018:08:28' ### @5='2016-08-12 15:36:09' # at 701 #181215 11:12:03 server id 1 end_log_pos 732 CRC32 0xc42a0c0d Xid = 7 COMMIT/*!*/; SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/; DELIMITER ;
五、二進制日志的刪除
1、reset mstaer 可以刪除所有日志文件 (不存在主從復制關系),執行完該語句,所有二進制日志被刪除。mysql重新創建二進制日志,編號從000001開始
2、purge master logs語句刪除指定日志文件
purge binary logs to 'DB-Server-bin.000002'; # 刪除該日志文件之前的所有日志文件
purge binary logs before '2017-03-10 10:10:00'; # 清除該時間點以前的所有日志文件
purge master logs before date_sub( now( ), interval 7 day); # 清除7天前的日志文件
六、使用二進制日志恢復數據庫
如果開啟了二進制日志,出現了數據丟失,可以通過二進制日志恢復數據庫,語法如下
mysqlbinlog [option] filename | mysql -u user -p passwd
option的參數主要有兩個 --start-datetime --stop-datetime 和 start-position --stop-position ,前者指定恢復的時間點,后者指定恢復的位置(位置指的是二進制文件中 # at 580 580就是位置)。原理就是把記錄的語句重新執行了一次,如果恢復了兩次。會產生重復數據。
mysqlbinlog --start-position="291" --stop-position="439" /data/3306/tmp/binlog/mysql-bin.000001 | mysql -uroot -p111111
注意,要找到插入更新的語句所在的時間點或位置。如果恢復的語句包含只有delete,會報錯1032錯誤。
七、暫時停止二進制日志功能
可以通過修改配置文件停止二進制日志功能,但是需要重啟數據庫,mysql提供了語句可以在線停止二進制功能
set sql_log_bin = 0 # 停止二進制日志功能 set sql_log_bin = 1 # 開啟二進制日志功能
八、二進制日志的三種模式
二進制日志三種格式:STATEMENT,ROW,MIXED,由參數binlog_format控制
1、STATEMENT模式(SBR)
每一條會修改數據的sql語句會記錄到binlog中。優點是並不需要記錄每一條sql語句和每一行的數據變化,減少了binlog日志量,節約IO,提高性能。缺點是在某些情況(如非確定函數)下會導致master-slave中的數據不一致(如sleep()函數, last_insert_id(),以及user-defined functions(udf)等會出現問題)
2、ROW模式(RBR)
不記錄每條sql語句的上下文信息,僅需記錄哪條數據被修改了,修改成什么樣了。而且不會出現某些特定情況下的存儲過程、或function、或trigger的調用和觸發無法被正確復制的問題。缺點是會產生大量的日志,尤其是alter table的時候會讓日志暴漲。
3、 MIXED模式(MBR)
以上兩種模式的混合使用,一般的復制使用STATEMENT模式保存binlog,對於STATEMENT模式無法復制的操作使用ROW模式保存binlog,MySQL會根據執行的SQL語句選擇日志保存方式