背景
binlog(binary log)是mysql的二进制日志,用于顺序记录数据库的逻辑变更。binlog记录DDL和DML等涉及数据库修改的操作,而不会记录Select和show等查询类操作。
由于顺序记录了数据库发生的变化,binlog承载了数据库的变化信息,可用于进行数据库数据复制和数据同步、数据恢复、数据审计等。
1.配置方式
在mysql8中binlog默认开启,而mysql5中默认关闭。
可在mysql的配置文件(默认/etc/my.cnf)中配置binog, 常见配置项如下所示:
[1] disable-log-bin 和 skip-log-bin
配置文件中添加disable-log-bin 和 skip-log-bin配置项可以关闭binlog
# 关闭binlog
skip-log-bin
[2] log-bin
log-bin用于配置指定二进制日志binlog的文件名前缀;
# 表示binlog文件以mysql-bin开头
log-bin=mysql-bin
[3] binlog-do-db
配置要记录binlog日志的数据库,且只对配置的数据库进行日志记录。当未配置binlog-do-db时,binlog对所有的数据库生效;配置了binlog-do-db=test_sy
后,binlog仅对test_sy数据库生效。
需要记录多个数据库时,配置多个binlog-do-db,如下所示:
# binglog仅记录数据库test_a,test_b,test_c的变化,忽略其他数据库
binlog-do-db=test_a
binlog-do-db=test_b
binlog-do-db=test_c
[4] binlog-ignore-table
配置需要忽略的表名,当需要忽略多个表(不记录日志)时,配置多个binlog-ignore-table项; 可以忽略不必要的数据同步,减少日志量。
[5] binlog-format
配置binlog的存储格式, 有三种配置方式:
(1) STATEMENT: 记录修改数据的SQL语句,此时文件较小,该模式存在非确定性问题,如NOW()、 UUID()和RAND()函数在不同场景下返回的值不同,导致实际的SQL语句不确定;
(2) ROW: 记录数据行的实际变化,日志量较大;
(3) MIXED:混合STATEMENT和ROW,对于非确定性SQL使用ROW记录,其他场景使用STATEMENT记录,混合了二者的优点
[6] binlog-row-image
根据记录行变更时记录信息的详细程度,分为三种配置方式:
(1) FULL:记录前镜像(修改前)和后镜像(修改后)的所有列的数据信息,较为安全,且有助于数据恢复和闪回操作,但是Binlog占据较大空间;
(2) NOBLOB:与FULL类型,记录前镜像(修改前)和后镜像(修改后)的所有列的数据信息;
区别在于对于BLOB 或 TEXT字段,如果不是唯一索引或者主键且没有发生变化,不进行记录;相对FULL可以减少binlog占据的空间;
(3) MINIMAL:最小化存储
前镜像:只记录唯一识别列(唯一索引、主键),如果没有唯一识别列,记录所有列;
后镜像:仅记录修改的列;
[7] expire_logs_days和binlog_expire_logs_seconds
expire_logs_days和binlog_expire_logs_seconds都用于配置binlog文件的超时时间,过时的日志将被清理。
区别时mysql5中使用expire_logs_days,而mysql8中使用binlog_expire_logs_seconds。binlog_expire_logs_seconds参数的默认值是 2592000 秒,这相当于 30 天
以上所有配置信息的修改,需要重启mysql生效。除了通过mysql的配置文件查看binlog配置外,还可通过查询语句查看binlog的配置信息:执行show variables like '%log_bin%';
或show variables like '%binlog%';
可以得到bin_log相关的配置信息;%log_bin%
查询命令得到如下变量信息:
[1] log_bin
表示binlog日志是否开启:ON表示开启,OFF表示关闭;对应配置文件中的skip-log-bin项; 当关闭binlog时,查询结果如下:
对应配置文件中的skip-log-bin项;
[2] log_bin_basename和log_bin_index
log_bin_basename表示binlog日志文件的前缀,log_bin_index表示binlog文件索引路径;对应配置文件的"log-bin=mysql-bin"配置项。
# 进入mysql目录下,查看binlog日志
[root@124 mysql]# cd /var/lib/mysql/
[root@124 mysql]# ls -al | grep mysql-bin
-rw-r-----. 1 mysql mysql 177 Nov 20 09:58 mysql-bin.000001
-rw-r-----. 1 mysql mysql 177 Nov 20 09:58 mysql-bin.000002
-rw-r-----. 1 mysql mysql 699 Nov 20 10:05 mysql-bin.000003
-rw-r-----. 1 mysql mysql 2465 Nov 20 10:16 mysql-bin.000004
-rw-r-----. 1 mysql mysql 37841 Nov 20 14:10 mysql-bin.000005
-rw-r-----. 1 mysql mysql 95 Nov 20 11:39 mysql-bin.index
[root@124 mysql]## mysql-bin.index文件索引记录了当前mysql拥有的Binlog日志文件路径
[root@124 mysql]# cat mysql-bin.index
./mysql-bin.000001
./mysql-bin.000002
./mysql-bin.000003
./mysql-bin.000004
./mysql-bin.000005
mysql-bin.000001~mysql-bin.000005都是生产的binlog日志。
2.binlog的创建和清理
2.1 创建binlog
如章节1.1中mysql-bin.index文件记录了5个binlog日志文件,也可通过show binary logs
命令查看。
binlog文件为啥会分开记录呢?拆分的契机又是什么?
mysql服务器重启、日志文件过大、手动执行flush logs
命令刷新日志时都会生成一个新的binlog文件.
max_binlog_size变量表示binlog的阈值,默认1G,表示单个binlog日志文件最大为1G。
2.2 清理binlog
可以通过reset master
命令清空binlog日志文件,如下所示:
此时,仅保留一个日志文件。
除手动清除外,通过章节1.1中介绍的binlog_expire_logs_seconds变量控制mysql清理超期的数据。
3.案例介绍
以下结合案例介绍binlog如何记录操作日志。
为展示方便,配置binlog-format为STATEMENT以及binlog-row-image为FULL(重启mysql后使配置生效)。
执行reset master
命令以清空历史binlog日志文件;依次执行如下sql语句:
-- step1: 创建test_db数据库
create database test_db;
use test_db;-- step2: 创建t_test表
CREATE TABLE `t_test` (`id` INT(11) NOT NULL AUTO_INCREMENT,`name` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;-- step3: 【insert操作】
INSERT INTO t_test(NAME) VALUES("a");-- step4: 【update】
update t_test set name = "b" where name = "a";-- step5: 【delete操作】
delete from t_test where name = "b";
得到mysql-bin.000001文件,借助sql语句和mysqlbinlog工具进行分析:
执行show binlog EVENTS IN 'mysql-bin.000001'
查询命令得到:
执行mysqlbinlog mysql-bin.000001
命令查看日志内容如下:
-- 省略注释、时间戳、事务相关...DELIMITER /*!*/;create database test_dbCREATE TABLE `t_test` (`id` INT(11) NOT NULL AUTO_INCREMENT,`name` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDBINSERT INTO t_test(NAME) VALUES("a")update t_test set name = "b" where name = "a"
delete from t_test where name = "b"DELIMITER ;
4.使用Binlog恢复数据
章节3中SQL案例的起始节点位置是154,结束节点是1565,如下所示:
通过开始位置和结束位置截取执行日志并生成sql文件:
mysqlbinlog --start-position=154 --stop-position=1596 mysql-bin.000001 > test_db_backup.sql
在另一台机器执行test_db_backup.sql后,执行查询操作:
mysql> source /home/sy/test_db_backup.sql;
Query OK, 0 rows affected (0.00 sec)-- ... 省略多行日志Query OK, 0 rows affected (0.00 sec)mysql> select * from test_db.t_test;
Empty set (0.00 sec)
此时,数据库、表和记录数据变化已同步到另一台机器。