MySQLbinlog日誌01binlog日誌基本操作
本系列博客主要介紹MySQL數據庫的binlog日誌的相關內容,這個系列的主題包括:
MySQLbinlog日誌01binlog日誌基本操作
MySQLbinlog日誌02binlog日誌用於數據恢復
MySQLbinlog日誌03binlog日誌字節碼解析
MySQLbinlog日誌04binlog日誌字節碼解析之二Write_Rows事件
本篇博客是第1篇,主要介紹binlog日誌基本操作。內容包括:
binlog日誌的作用
binlog日誌相關的配置參數
binlog相關的SQL語句
binlog日誌內容查看
以下是本博客的正文:
binlog日誌的作用
binlog日誌記錄了一段時間內數據庫上的所有寫數據操作的完整數據。因此在數據不一致或者誤操作刪除數據後,可以用於某個時間段或者某個
binlog日誌的另外一個工作能用於MySQL主從復制體系。主機上產生binlog日誌數據,並且發送到從機上。從機上的IO線程接收到事件數據後保存到本地的relay event日誌中,從機的SQL線程隨後將這些relay event日誌中的事件數據在從機上執行,從而達到主從一致的狀態。
binlog日誌相關的配置參數
比較重要的幾個參數:
log_bin=mysql_binlog
binlog日誌文件的文件名前綴
sync_binlog=1
執行多個事務後同步binlog日誌文件。
0:不同步,僅僅寫入binlog緩存。
1:1個事務後同步。
N(N>1):N個事務後同步。
max_binlog_size=10M
一個binlog日誌文件的最大大小。 最小值為4096字節。
binlog_format=row
binlog事件的格式。
ROW:記錄行數據,默認不記錄用戶SQL,對於DDL語句,仍然記錄SQL。
STATEMENT:記錄用戶sql語句。當執行一些函數時導致復制機制產生問題,數據不一致。
MIXED:主要記錄sql語句,當用到了特定的函數時記錄行數據。
在ROW模式下,如果delete語句實際沒有刪除任何記錄,則不會記錄到binlog日誌中。
對於一個UPDATE語句修改了多條記錄,則每一條記錄會作為一個
binlog_row_image=full
記錄行數據(ROW模式)時,是否記錄沒有使用到的字段的值。
FULL:記錄所有字段,包括沒有使用的字段。
MINIMAL:只記錄被更改的字段和能夠唯一識別記錄的字段的值。
NOBLOB:基本跟FULL相同,但是沒有使用到的TEXT和BLOB字段除外。
binlog_rows_query_log_events=1
是否記錄用戶的原始SQL,用於ROW模式。
0:不記錄。
1:記錄。
全部的參數如下所示:
mysql> show variables like ‘%binlog%‘
-> ;
+--------------------------------------------+----------------------+
| Variable_name | Value |
+--------------------------------------------+----------------------+
| binlog_cache_size | 32768 |
| binlog_checksum | CRC32 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_error_action | ABORT_SERVER |
| binlog_format | ROW |
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_gtid_simple_recovery | ON |
| binlog_max_flush_queue_time | 0 |
| binlog_order_commits | ON |
| binlog_row_image | FULL |
| binlog_rows_query_log_events | ON |
| binlog_stmt_cache_size | 32768 |
| binlog_transaction_dependency_history_size | 25000 |
| binlog_transaction_dependency_tracking | COMMIT_ORDER |
| innodb_api_enable_binlog | OFF |
| innodb_locks_unsafe_for_binlog | OFF |
| log_statements_unsafe_for_binlog | ON |
| max_binlog_cache_size | 18446744073709547520 |
| max_binlog_size | 10485760 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| sync_binlog | 1 |
+--------------------------------------------+----------------------+
22 rows in set (0.01 sec)
binlog相關的SQL語句
清除全部的binlog文件。
o RESET MASTER
Deletes all binary logs listed in the index file, resets the binary
log index file to be empty, and creates a new binary log file.
mysql> reset master;
Query OK, 0 rows affected (0.01 sec)
查看當前全部binlog文件的名字和大小。
mysql> show binary logs;
+---------------------+-----------+
| Log_name | File_size |
+---------------------+-----------+
| mysql_binlog.000001 | 154 |
+---------------------+-----------+
1 row in set (0.00 sec)
File_size列出的就是binlog文件的字節數大小。
[root@101 data]# ls -l mysql_binlog.*
-rw-r-----. 1 mysql mysql 154 Sep 20 20:46 mysql_binlog.000001
-rw-r-----. 1 mysql mysql 22 Sep 20 20:46 mysql_binlog.index
查看binlog的最新位置,也是154,就是這個位置(Position)實際上是文件的字節偏移量。
mysql> help show master status
Name: ‘SHOW MASTER STATUS‘
Description:
Syntax:
SHOW MASTER STATUS
This statement provides status information about the binary log files
of the master. It requires either the SUPER or REPLICATION CLIENT
privilege.
mysql> show master status;
+---------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------+----------+--------------+------------------+-------------------+
| mysql_binlog.000001 | 154 | | | |
+---------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql> show binlog events in ‘mysql_binlog.000001‘;
+---------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+---------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql_binlog.000001 | 4 | Format_desc | 101 | 123 | Server ver: 5.7.22-log, Binlog ver: 4 |
| mysql_binlog.000001 | 123 | Previous_gtids | 101 | 154 | |
+---------------------+-----+----------------+-----------+-------------+---------------------------------------+
2 rows in set (0.00 sec)
刷新binlog文件,即新建立一個binlog日誌文件。
mysql> show binary logs;
+---------------------+-----------+
| Log_name | File_size |
+---------------------+-----------+
| mysql_binlog.000001 | 154 |
+---------------------+-----------+
1 row in set (0.00 sec)
mysql> flush binary logs;
Query OK, 0 rows affected (0.00 sec)
mysql> flush binary logs;
Query OK, 0 rows affected (0.00 sec)
mysql> show binary logs;
+---------------------+-----------+
| Log_name | File_size |
+---------------------+-----------+
| mysql_binlog.000001 | 204 |
| mysql_binlog.000002 | 204 |
| mysql_binlog.000003 | 154 |
+---------------------+-----------+
3 rows in set (0.00 sec)
flush logs, flush tables with read , flush tables for export這些命令不會寫binlog日誌,因為如果寫了binlog,可能會在主從復制時產生問題。
FLUSH LOGS, FLUSH TABLES WITH READ LOCK (with or without a table list),
and FLUSH TABLES tbl_name ... FOR EXPORT are not written to the binary
log in any case because they would cause problems if replicated to a
slave.
show binlog events 語句用於查看指定的binlog日誌文件中記錄的binlog事件。
binlog日誌內容查看
假定目前binlog_format=row。
先用flush logs創建一個新的binlog文件。
mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;
+---------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------+----------+--------------+------------------+-------------------+
| mysql_binlog.000046 | 154 | | | |
+---------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
使用mysqlbinlog程序查看文件內容,DECODE-ROWS選項表示解析原始輸出信息中的BASE64數據塊為SQL語句,否則將看到BASE64數據塊。
[root@101 data]# mysqlbinlog -v --base64-output=DECODE-ROWS mysql_binlog.000046
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#180920 0:09:37 server id 101 end_log_pos 123 CRC32 0xc5c14f6f Start: binlog v 4, server v 5.7.22-log created 180920 0:09:37
# Warning: this binlog is either in use or was not closed properly.
# at 123
#180920 0:09:37 server id 101 end_log_pos 154 CRC32 0xa91b6a91 Previous-GTIDs
# [empty]
SET @@SESSION.GTID_NEXT= ‘AUTOMATIC‘ /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
使用下面的命令去掉mysqlbinlog輸出中的註釋語句,使得輸出的日誌信息更容易觀察。
root@101 data]# mysqlbinlog -v --base64-output=DECODE-ROWS mysql_binlog.000046 |grep -E -v "^\/\*"
DELIMITER /*!*/;
# at 4
#180920 0:09:37 server id 101 end_log_pos 123 CRC32 0xc5c14f6f Start: binlog v 4, server v 5.7.22-log created 180920 0:09:37
# Warning: this binlog is either in use or was not closed properly.
# at 123
#180920 0:09:37 server id 101 end_log_pos 154 CRC32 0xa91b6a91 Previous-GTIDs
# [empty]
SET @@SESSION.GTID_NEXT= ‘AUTOMATIC‘ /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
mysql_binlog.000046文件的日誌從position=4的位置開始,到end_log_pos=154結束,這個文件是mysql當前產生的最新的一個binlog文件,end_log_pos與show master status的輸出信息的position的值相同。由此可見,show master status輸出的position是最新的binlog文件的末尾位置。
在搭建主從復制架構時,從機的change master to語句中的master_log_position=xxxxx,這個xxxxx值不能簡單的賦值為show master status的position值。應該考慮實際情況再決定使用什麽數值。
如果從機是按照主機的最新的備份制作的數據庫,那麽可以使用show master status的position值,此時master_log_file也應該是這裏輸出的file的值。
如果從機不是按照最新的備份制作的數據庫,那麽需要仔細分析後根據位置信息和文件信息以及具體時間點進行設置。
執行一個SQL語句。
mysql> show master status;
+---------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------+----------+--------------+------------------+-------------------+
| mysql_binlog.000046 | 154 | | | |
+---------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql> insert into t2 (name) values (‘A1‘),(‘B1‘);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> show master status;
+---------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------+----------+--------------+------------------+-------------------+
| mysql_binlog.000046 | 421 | | | |
+---------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
binlog Position從154變成了421。
查看新的binlog日誌:
root@101 data]# mysqlbinlog -v --base64-output=DECODE-ROWS mysql_binlog.000046 |grep -E -v "^\/\*"
DELIMITER /*!*/;
# at 4
#180920 0:09:37 server id 101 end_log_pos 123 CRC32 0xc5c14f6f Start: binlog v 4, server v 5.7.22-log created 180920 0:09:37
# Warning: this binlog is either in use or was not closed properly.
# at 123
#180920 0:09:37 server id 101 end_log_pos 154 CRC32 0xa91b6a91 Previous-GTIDs
# [empty]
# at 154
#180920 0:23:30 server id 101 end_log_pos 219 CRC32 0xc8b9a40f Anonymous_GTIDlast_committed=0 sequence_number=1 rbr_only=yes
SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘/*!*/;
# at 219
#180920 0:23:30 server id 101 end_log_pos 291 CRC32 0xb2d919c9 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1537374210/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
# at 291
#180920 0:23:30 server id 101 end_log_pos 339 CRC32 0x097d51d0 Table_map: `test`.`t2` mapped to number 110
# at 339
#180920 0:23:30 server id 101 end_log_pos 390 CRC32 0x025373f6 Write_rows: table id 110 flags: STMT_END_F
### INSERT INTO `test`.`t2`
### SET
### @1=1
### @2=‘A1‘
### INSERT INTO `test`.`t2`
### SET
### @1=2
### @2=‘B1‘
# at 390
#180920 0:23:30 server id 101 end_log_pos 421 CRC32 0x077fb982 Xid = 26
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= ‘AUTOMATIC‘ /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
在position=339的地方寫入一個事務的2條新記錄,然後執行了提交操作,end_log_pos=421。
執行2條update語句:
mysql> update t2 set name=‘AAAA1‘ where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update t2 set name=‘AAAA2‘ where id=2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
繼續查看binlog日誌信息,使用--start-position選項指定從position=421(之前的binlog日誌前面已經查看過了)開始查看binlog日誌。
[root@101 data]# mysqlbinlog --start-position=421 -v --base64-output=DECODE-ROWS mysql_binlog.000046 |grep -E -v "^\/\*"
DELIMITER /*!*/;
# at 421
#180920 0:30:38 server id 101 end_log_pos 486 CRC32 0x45344b55 Anonymous_GTIDlast_committed=1 sequence_number=2 rbr_only=yes
SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘/*!*/;
# at 486
#180920 0:30:38 server id 101 end_log_pos 558 CRC32 0xdb968326 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1537374638/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
# at 558
#180920 0:30:38 server id 101 end_log_pos 606 CRC32 0xe179cc2d Table_map: `test`.`t2` mapped to number 110
# at 606
#180920 0:30:38 server id 101 end_log_pos 661 CRC32 0x26f63b69 Update_rows: table id 110 flags: STMT_END_F
### UPDATE `test`.`t2`
### WHERE
### @1=1
### @2=‘A1‘
### SET
### @1=1
### @2=‘AAAA1‘
# at 661
#180920 0:30:38 server id 101 end_log_pos 692 CRC32 0x2dcc1cd6 Xid = 29
COMMIT/*!*/;
# at 692
#180920 0:30:53 server id 101 end_log_pos 757 CRC32 0x07b40b05 Anonymous_GTIDlast_committed=2 sequence_number=3 rbr_only=yes
SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘/*!*/;
# at 757
#180920 0:30:53 server id 101 end_log_pos 829 CRC32 0xbbb5f160 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1537374653/*!*/;
BEGIN
# at 829
#180920 0:30:53 server id 101 end_log_pos 877 CRC32 0x96ab4362 Table_map: `test`.`t2` mapped to number 110
# at 877
#180920 0:30:53 server id 101 end_log_pos 932 CRC32 0x9b9c8a78 Update_rows: table id 110 flags: STMT_END_F
### UPDATE `test`.`t2`
### WHERE
### @1=2
### @2=‘B1‘
### SET
### @1=2
### @2=‘AAAA2‘
# at 932
#180920 0:30:53 server id 101 end_log_pos 963 CRC32 0x1c975da3 Xid = 30
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= ‘AUTOMATIC‘ /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
mysqlbinlog程序輸出的日誌信息中,可以看到數據庫中執行的寫操作的SQL語句的基本原型,不包含字段名稱。字段名全部都使用@1,@2等代替了,這裏@1表示第1個字段,@2表示第2個字段,依次類推。由於這些SQL中已經包含了表名,可以很容易取到字段的順序以及名稱。因此,可以根據這些SQL語句還原出真實的包含了字段名的SQL語句。
mysql> desc t2;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(100) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
### UPDATE `test`.`t2`
### WHERE
### @1=2
### @2=‘B1‘
### SET
### @1=2
### @2=‘AAAA2‘
這個語句中的@1就是id,@2就是name。
-v參數的效果:
### INSERT INTO `test`.`t2`
### SET
### @1=3
### @2=‘3‘
### @3=0
### @4=NULL
當使用-vv參數時,將包含每個字段的詳細元數據信息。
### INSERT INTO `test`.`t2`
### SET
### @1=3 /* INT meta=0 nullable=0 is_null=0 */
### @2=‘3‘ /* VARSTRING(100) meta=100 nullable=0 is_null=0 */
### @3=0 /* INT meta=0 nullable=0 is_null=0 */
### @4=NULL /* INT meta=0 nullable=1 is_null=1 */
在使用-vv參數,同時配置參數binlog_rows_query_log_events=1的效果:
binlog中將會包含用戶執行的原始SQL語句。
# at 291
#180920 6:56:10 server id 101 end_log_pos 355 CRC32 0x24cd5468 Rows_query
# insert into t2 (name) values (‘3‘),(‘4‘)
# at 355
#180920 6:56:10 server id 101 end_log_pos 405 CRC32 0x6d5e9163 Table_map: `test`.`t2` mapped to number 108
# at 405
#180920 6:56:10 server id 101 end_log_pos 462 CRC32 0x3d3d565b Write_rows: table id 108 flags: STMT_END_F
### INSERT INTO `test`.`t2`
### SET
### @1=3 /* INT meta=0 nullable=0 is_null=0 */
### @2=‘3‘ /* VARSTRING(100) meta=100 nullable=0 is_null=0 */
### @3=0 /* INT meta=0 nullable=0 is_null=0 */
### @4=NULL /* INT meta=0 nullable=1 is_null=1 */
### INSERT INTO `test`.`t2`
### SET
### @1=4 /* INT meta=0 nullable=0 is_null=0 */
### @2=‘4‘ /* VARSTRING(100) meta=100 nullable=0 is_null=0 */
### @3=0 /* INT meta=0 nullable=0 is_null=0 */
### @4=NULL /* INT meta=0 nullable=1 is_null=1 */
MySQLbinlog日誌01binlog日誌基本操作