说起MySQL binlog,并不陌生,经常听到DBA们提到,可以说是如雷贯耳。
那binlog到底是什么,有什么用途,以及如何使用,本文将围绕这个主题展开。
与MySQL Server相关的日志主要有4种:
在binlog中,这些变更操作统称为事件(Event)。
对于支持事务的存储引擎来说,例如InnoDB,只有事务提交后才会记录binlog。至于binlog什么时候刷新到磁盘,这个跟参数sync_binlog 有关。
在使用InnoDB时,为了保证数据一致性,推荐的设置是
sync_binlog=1
innodb_flush_log_at_trx_commit=1
innodb_flush_log_at_trx_commit=1表示每次事务提交都会刷新到磁盘。
当数据写入数据库后,会将变更操作写入binlog文件。
binlog的作用主要有两个:
binlog有三种格式:
由于基于Row的格式,数据准确性高等特点,是目前用的最多的。
binlog日志文件包括两种:索引文件和具体日志文件。
索引文件用于跟踪日志文件,每行一个日志文件。
默认情况下,索引文件名为{Host名}-bin.index。
日志文件是由一系列事件(Binary Log Events)组成。默认情况下,文件名为{Host名}-bin.NNNNNN。 后缀六个数字,是编号,用于区分不同的日志文件。
日志文件的开头是 Format_description 事件,这个事件记录主库的信息和日志文件的状态。如果主库突然宕机或者重启,会重新创建一个日志文件,并在开头写入Format_description。
当需要创建一个新日志文件时,会写入Rotate事件。Rotate事件会指定下一个日志文件的文件名和读取事件的起始点。
日志文件会把除了Format_description事件和Rotate事件之外的其他变更事件进行分组(Group)。在MySQL中,每一个事务会被分成一组,组中包含了这个事务下执行的所有语句。一些非事务性语句会被单独分成一组,如create和drop语句等。如下图所示。
每个binlog事件由四个部分组成:
当遇到以下3种情况时会重新生成一个新的日志文件,文件序号递增:
在MySQL配置文件my.cnf中增加log-bin参数即可开启binlog:
[mysqld]
log-bin=mysql-bin
也可指定具体的文件路径:
log_bin = /var/mysql/logs/mysql-bin
修改配置文件后,需要重启MySQL服务。
通过命令行的方式开启和关闭binlog:
(1)过期删除
mysql> show variables like 'expire_log_days';
mysql> set global expire_log_days=7;
(2)reset master 会删除所有binlog
(3) reset slave 会删除所有relay log
查看日志文件
> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 16899 |
+------------------+-----------+
1 row in set (0.00 sec)
或者
>show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 16899 |
+------------------+-----------+
1 row in set (0.01 sec)
查看日志文件位置
show master status;
+------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+
| mysql-bin.000001 | 16899 | | | 10035945-aaaa-11e9-89f3-0022ac533a99:1-67|
+------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
查看日志文件内容
binlog日志文件不是文本文件,不能直接通过vim,cat等查看。
需要使用mysql命令或者mysqlbinlog命令。
>show binlog events in 'mysql-bin.000001';
+------------------+-------+----------------+-----------+-------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-------+----------------+-----------+-------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mysql-bin.000001 | 4 | Format_desc | 20201066 | 120 | Server ver: 5.6.36-82.1-log, Binlog ver: 4 |
| mysql-bin.000001 | 120 | Previous_gtids | 20201066 | 151 | |
| mysql-bin.000001 | 151 | Gtid | 20201066 | 199 | SET @@SESSION.GTID_NEXT= '10035966-ddeb-11e9-89f3-0022ac533a2f:1' |
| mysql-bin.000001 | 199 | Query | 20201066 | 319 | create database if not exists app_test |
| mysql-bin.000001 | 319 | Gtid | 20201066 | 367 | SET @@SESSION.GTID_NEXT= '10035966-ddeb-11e9-89f3-0022ac533a2f:2' |
| mysql-bin.000001 | 367 | Query | 20201066 | 488 | create table if not exists app_test.abc (a int) |
| mysql-bin.000001 | 488 | Gtid | 20201066 | 536 | SET @@SESSION.GTID_NEXT= '10035966-ddeb-11e9-89f3-0022ac533a2f:3' |
| mysql-bin.000001 | 536 | Query | 20201066 | 776 | GRANT CREATE, SHUTDOWN, SUPER, LOCK TABLES, REPLICATION CLIENT, REPLICATION SLAVE, RELOAD, PROCESS, TRIGGER ON *.* TO 'orange_manager'@'10.10.116.88' |
| mysql-bin.000001 | 776 | Gtid | 20201066 | 824 | SET @@SESSION.GTID_NEXT= '10035966-ddeb-11e9-89f3-0022ac533a2f:4' |
| mysql-bin.000001 | 824 | Query | 20201066 | 993 | GRANT SELECT ON `mysql`.`slave_master_info` TO 'orange_manager'@'10.10.116.88' |
| mysql-bin.000001 | 993 | Gtid | 20201066 | 1041 | SET @@SESSION.GTID_NEXT= '10035966-ddeb-11e9-89f3-0022ac533a2f:5' |
| mysql-bin.000001 | 1041 | Query | 20201066 | 1213 | GRANT SELECT ON `mysql`.`slave_relay_log_info` TO 'orange_manager'@'10.10.116.88' |
或者使用mysqlbinlog命令,在shell终端输入:
mysqlbinlog /var/logs/mysql-bin.000001
类似如下内容:
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#161020 11:07:29 server id 2 end_log_pos 107 Start: binlog v 4, server v 5.5.51-log created 161020 11:07:29
# Warning: this binlog is either in use or was not closed properly.
BINLOG '
8TQIWA8CAAAAZwAAAGsAAAABAAQANS41LjUxLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAVAAEGggAAAAICAgCAA==
'/*!*/;
# at 107
#161020 11:08:50 server id 2 end_log_pos 181 Query thread_id=162 exec_time=1 error_code=0
SET TIMESTAMP=1476932930/*!*/;
SET @@session.pseudo_thread_id=162/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
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/*!*/;
提取指定的binlog日志
例如,insert相关的:
# mysqlbinlog /opt/logs/mysql-bin.000001 | grep insert
或者提取指定位置的binlog日志
# mysqlbinlog --start-position="109" --stop-position="320" /opt/logs/mysql-bin.000001
提取指定位置的binlog日志并输出到压缩文件
# mysqlbinlog --start-position="109" --stop-position="320" /opt/logs/mysql-bin.000001 |gzip >tmp.sql.gz
提取指定位置的binlog日志导入数据库
# mysqlbinlog --start-position="108" --stop-position="226" /opt/logs/mysql-bin.000001 | mysql -uroot -p
提取指定开始时间的binlog并输出到日志文件
# mysqlbinlog --start-datetime="2020-07-02 22:16:23" /opt/log/mysql-bin.000002 --result-file=tmp02.sql
提取多个binlog日志文件的指定位置的日志
# mysqlbinlog --start-position="108" --stop-position="226" /opt/logs/mysql-bin.000001 /opt/logs/mysql-bin.000002|more
提取指定数据库binlog并转换字符集到UTF8
# mysqlbinlog --database=test --set-charset=utf8 /opt/logs/mysql-bin.000001 /opt/logs/mysql-bin.000002 >test.sql
远程提取日志,指定结束时间
# mysqlbinlog -uroot -p -h192.168.1.186 -P3306 --stop-datetime="2020-06-23 20:30:23" --read-from-remote-server mysql-bin.000033 |more