Day05 02-MySQL bin-log日志原理与实践详解

文章目录

      • 第十五章 bin-log日志
        • 15.1 MySQL的日志
        • 15.2 启用bin-log
          • 15.2.1 查看bin-log是否开启
          • 15.2.2 通过配置文件禁用bin-log
          • 15.2.3 通过命令禁用bin-log
        • 15.3 常用命令
        • 15.4 bin-log生成的时机
          • 15.4.1 写bin-log的时机
          • 15.4.2 生成新的bin-log文件
        • 15.5 bin-log文件解析
          • 15.5.1 bin-log日志格式
          • 15.5.2 三种日志格式的区别
          • 15.5.3 bin-log文件描述
            • 15.5.3.1 bin-log日志文件查看
            • 15.5.3.2 bin-log日志文件组成
            • 15.5.3.3 bin-log日志文件事件
            • 15.5.3.4 bin-log中的事件查看
        • 15.6 bin-log恢复数据
          • 15.6.1 准备工作
          • 15.6.2 恢复数据

第十五章 bin-log日志

15.1 MySQL的日志

MySQL在服务启停、执行SQL的时候,会有各种日志的生成,这些日志可以分为以下类型:

日志类型 日志内容
错误日志 记录MySQL在运行、启动、停止的时候遇到的错误信息
通用查询日志 记录建立的客户端连接和执行的语句
二进制日志 DML操作,修改数据库的数据操作的日志
中继日志 从主服务器接收的数据更改日志
慢查询日志 查询时间超过long_query_time设定的时间,或者不使用索引的查询
DDL日志 DDL操作,涉及到元数据的变更的日志

其中,二进制日志中记录的是DML的操作,也就是增、删、改数据的日志信息,称为binary-log,也就是我们要说的bin-log日志。

MySQL的bin-log日志,可以说是上述的日志中最重要的日志。其中记录的不仅仅是DML的操作,DDL的操作也会记录在其中。可以说除了查询操作(select、show),都会记录在这样的日志中!

bin-log日志中,以事件的新式记录日志,记录你进行的SQL操作,同时还记录操作所消耗的时间等信息。学习bin-log日志最主要的目的是为了复制和恢复

  • 复制: MySQL的主从架构下,Master将二进制日志传递给Slaves,以达到Master和Slaves之间的数据一致性。
  • 恢复: 通过mysqlbinlog工具,恢复数据。

15.2 启用bin-log

15.2.1 查看bin-log是否开启

MySQL8的bin-log日志是默认开启的,因此我们更多关注如何关闭即可。

mysql> show variables like 'log_bin%';

# +---------------------------------+-----------------------------+
# | Variable_name                   | Value                       |
# +---------------------------------+-----------------------------+
# | log_bin                         | ON                          |
# | log_bin_basename                | /var/lib/mysql/binlog       |
# | log_bin_index                   | /var/lib/mysql/binlog.index |
# | log_bin_trust_function_creators | OFF                         |
# | log_bin_use_v1_row_events       | OFF                         |
# +---------------------------------+-----------------------------+
#
# 其中 log_bin 的值为ON,表示bin-log已经开启。
15.2.2 通过配置文件禁用bin-log
  • 通过修改MySQL的配置文件可以关闭bin-log日志:

    配置文件的路径:
    
    - Windows: C:\Program Data\MySQL\MySQL Server8.0\my.ini
    - Mac通过dmg直接安装: /etc/my.cnf
    - Mac通过HomeBrew安装: $HOMEBREW_HOME/etc/my.cnf
    - CentOS: /etc/my.cnf
    
  • 在 [mysqld] 标签下添加

    skip-log-bin
    
  • 重启MySQL服务

15.2.3 通过命令禁用bin-log
-- 禁用bin-log
mysql> SET SQL_LOG_BIN=0;
-- 启用bin-log
mysql> SET SQL_LOG_BIN=1;

-- 设置完成后需要重启MySQL服务生效

15.3 常用命令

-- 查看是否启用bin-log日志
show variables like 'log_bin';

-- 查看bin-log日志的目录
show variables like '%log_bin%';

-- 查看使用的bin-log文件大小
show binary logs;

-- 查看正在使用的bin-log文件名和Position
show master status;

-- 查看bin-log文件内容,默认查看第一个bin-log文件
show binlog events;

-- 查看指定的bin-log文件内容
show binlog events in 'binlog.000003';

-- 查看指定的bin-log文件内容,从指定位置开始查看
show binlog events in 'binlog.000003' from 865;

-- 查看指定的bin-log文件内容,从指定位置开始查看,查看指定偏移量
show binlog events in 'binlog.000003' from 125 limit 3;

-- 设置bin-log文件保存时间,单位是天
-- set global expire_log_days=3; MySQL8以下
-- 方式一:
set global binlog_expire_logs_seconds=2592000;
-- 方式二:在配置文件中修改 my.cnf / my.ini

-- 删除当前的bin-log文件
reset master;

15.4 bin-log生成的时机

15.4.1 写bin-log的时机
  • 事务执行过程中,会将日志写入到binlog-cache。系统为每一个线程分配了一个binlog-cache,大小由binlog_cache_size来控制。如果写入的数据量超出了这个大小,会暂存到磁盘,生成临时的文件。
  • 事务提交后,会将binlog-cache内的日志写入到binlog。如果有临时文件的生成,也会将临时文件中的数据写入到binlog。写入完成后,清除binlog-cache的内容并删除临时文件。
  • binlog的内容持久化到磁盘,这个过程会占用磁盘的IO。

由上述过程可以看出,持久化到磁盘的bin-log文件中的是最后一步。而在这里,需要了解一个参数: sync_binlog。这个参数表示提交多少个事务之后,将binlog的内容持久化到磁盘文件中。

  • sync_binlog=0

    每次提交事务都只会提交到binlog中,不会持久化到磁盘文件中。
    
  • sync_binlog=1

    每次提交事务都会把日志持久化到磁盘文件中。
    
  • sync_binlog=N

    例如设置为100,意义为提交100个事务,将日志持久化到磁盘文件中。
    

sync_binlog的值设置

通常情况下,我们会在1和N之间进行选择:

1:
	优点: 安全,不会丢失事务。
	缺点: 磁盘IO消耗高。
	
N:
	优点: 效率高,不会占用太多的磁盘IO。
	缺点: 不安全,如果服务器异常重启,会丢失最近N个事务的binlog日志。
15.4.2 生成新的bin-log文件
  • MySQL服务停止或重启
  • 当前正在使用的binlog文件大小超过上限(max_binlog_size)
  • 使用flush logs命令刷新

15.5 bin-log文件解析

15.5.1 bin-log日志格式

bin-log日志格式有三种类型:

  • STATEMENT
  • ROW
  • MIXED

在MySQL5.7.7之前,默认的格式是STATEMENT,5.7.7之后,默认的格式是ROW,可以通过binlog_format参数来设置日志的格式:

binlog_format=STATEMENT
binlog_format=ROW
binlog_format=MIXED
15.5.2 三种日志格式的区别
  • STATEMENT

    每一条会修改数据的SQL操作(DDL、DML)都会记录在bin-log中。
    
    - 优点:
        不需要记录每一行的变化,减少bin-log日志量,减少磁盘消耗,提高性能。
    
    - 缺点:
        主从模式下,有些语句不支持;容易出现主从不一致。
    
  • ROW

    5.1.5版本开始,MySQL支持了ROW格式,也是现在的默认的日志格式。这种格式下,不记录SQL语句,仅保存哪条记录被修改了。
    
    - 优点:
        1. 会记录每一条记录被修改的细节。
        2. 在主从模式下,不会出现存储过程、function、触发器无法被正确复制的问题。
       
    - 缺点:
        会产生大量的日志内容。
    
  • MIXED

    从5.1.8版本开始,MySQL支持Mixed格式。这种其实其实是STATEMENT和ROW格式的结合。
    - 一般的语句修改使用STATEMENT格式保存bin-log。
    - 对应STATEMENT无法完成的主从复制操作,例如存储过程、函数等,采用ROW格式保存bin-log。
    
15.5.3 bin-log文件描述

bin-log日志文件包含两类:

  • binlog.index

    索引文件,是一个普通的文本文件,可以直接查看里面的内容。其中记录的是当前的bin-log文件列表。
    
  • binlog.0000*

    这种文件是二进制文件,其中记录着操作的日志。
    
15.5.3.1 bin-log日志文件查看
# 查看bin-log二进制文件中的所有内容
mysqlbinlog -v --base64-output=decode-rows binlog.000001

# 查看bin-log二进制文件中指定范围的内容
mysqlbinlog -v --base64-output=decode-rows binlog.000001 \
--start-position="100" \
--stop-position="1000" \
--start-datetime="2021-01-01 10:00:05" \
--stop-datetime="2021-01-10 12:00:00"
15.5.3.2 bin-log日志文件组成

bin-log日志文件中记录的都是一些事件Event,其中第一个Event表示当前日志文件的起点和格式,最后一个Event表示下一个日志的起点和格式。中间的都是当前日志文件中记录的事件信息。

15.5.3.3 bin-log日志文件事件
# at 235
#220126 23:18:44 server id 1  end_log_pos 475 CRC32 0x5372bdc8  Query   thread_id=8     exec_time=0     error_code=0    Xid = 9
SET TIMESTAMP=1643210324.145384/*!*/;
SET @@session.pseudo_thread_id=8/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/;
SET @@session.time_zone='SYSTEM'/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
ALTER USER 'root'@'localhost' IDENTIFIED WITH 'caching_sha2_password' AS '$A$005$h^X^Sc^A^VI    ^D/!^]%N-^K^K^CYn7vZ6L6SMh9v5bwFvMZSqDcl6sEH.8quuhEr4C.ASsx9'
/*!*/;

这是我截取到的一部分的event,其中包含以下内容:

  • position:

    第一行的at 235,表示这条事件记录是从文件的第235个字节开始
    
  • timestamp:

    第二行的,#220126 23:18:44,表示这个事件发生的时间
    
  • server id:

    事件发生的服务器标识
    
  • end_log_pos:

    当前事件的结束位置+1,即下一个事件的起始位置
    
  • thread_id:

    执行这个事件的线程id
    
  • exec_time:

    执行这个事件花费的时间
    
  • error_code:

    事件的错误码,0表示没有错误
    
15.5.3.4 bin-log中的事件查看

我们可以通过查看bin-log文件,查看文件中保存的事件,也可以通过命令,更加直观的查看。

mysql> show binlog events in 'binlog.000015';
+---------------+------+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------+
| Log_name      | Pos  | Event_type     | Server_id | End_log_pos | Info                                                                                              |
+---------------+------+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------+
| binlog.000015 |    4 | Format_desc    |         1 |         125 | Server ver: 8.0.27, Binlog ver: 4                                                                 |
| binlog.000015 |  125 | Previous_gtids |         1 |         156 |                                                                                                   |
| binlog.000015 |  156 | Anonymous_Gtid |         1 |         233 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                              |
| binlog.000015 |  233 | Query          |         1 |         394 | use `mydb2`; create table user(`uid` int primary key, `name` varchar(20), `age` int) /* xid=41 */ |
| binlog.000015 |  394 | Anonymous_Gtid |         1 |         473 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                              |
| binlog.000015 |  473 | Query          |         1 |         549 | BEGIN                                                                                             |
| binlog.000015 |  549 | Table_map      |         1 |         609 | table_id: 100 (mydb2.user)                                                                        |
| binlog.000015 |  609 | Write_rows     |         1 |         662 | table_id: 100 flags: STMT_END_F                                                                   |
| binlog.000015 |  662 | Xid            |         1 |         693 | COMMIT /* xid=42 */                                                                               |
| binlog.000015 |  693 | Anonymous_Gtid |         1 |         772 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                              |
| binlog.000015 |  772 | Query          |         1 |         848 | BEGIN                                                                                             |
| binlog.000015 |  848 | Table_map      |         1 |         908 | table_id: 100 (mydb2.user)                                                                        |
| binlog.000015 |  908 | Write_rows     |         1 |         957 | table_id: 100 flags: STMT_END_F                                                                   |
| binlog.000015 |  957 | Xid            |         1 |         988 | COMMIT /* xid=43 */                                                                               |
| binlog.000015 |  988 | Anonymous_Gtid |         1 |        1067 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                              |
| binlog.000015 | 1067 | Query          |         1 |        1143 | BEGIN                                                                                             |
| binlog.000015 | 1143 | Table_map      |         1 |        1203 | table_id: 100 (mydb2.user)                                                                        |
| binlog.000015 | 1203 | Write_rows     |         1 |        1254 | table_id: 100 flags: STMT_END_F                                                                   |
| binlog.000015 | 1254 | Xid            |         1 |        1285 | COMMIT /* xid=44 */                                                                               |
| binlog.000015 | 1285 | Anonymous_Gtid |         1 |        1364 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                              |
| binlog.000015 | 1364 | Query          |         1 |        1440 | BEGIN                                                                                             |
| binlog.000015 | 1440 | Table_map      |         1 |        1500 | table_id: 100 (mydb2.user)                                                                        |
| binlog.000015 | 1500 | Write_rows     |         1 |        1552 | table_id: 100 flags: STMT_END_F                                                                   |
| binlog.000015 | 1552 | Xid            |         1 |        1583 | COMMIT /* xid=45 */                                                                               |
| binlog.000015 | 1583 | Anonymous_Gtid |         1 |        1662 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                              |
| binlog.000015 | 1662 | Query          |         1 |        1738 | BEGIN                                                                                             |
| binlog.000015 | 1738 | Table_map      |         1 |        1798 | table_id: 100 (mydb2.user)                                                                        |
| binlog.000015 | 1798 | Write_rows     |         1 |        1849 | table_id: 100 flags: STMT_END_F                                                                   |
| binlog.000015 | 1849 | Xid            |         1 |        1880 | COMMIT /* xid=46 */                                                                               |
| binlog.000015 | 1880 | Anonymous_Gtid |         1 |        1959 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                              |
| binlog.000015 | 1959 | Query          |         1 |        2044 | BEGIN                                                                                             |
| binlog.000015 | 2044 | Table_map      |         1 |        2104 | table_id: 100 (mydb2.user)                                                                        |
| binlog.000015 | 2104 | Update_rows    |         1 |        2172 | table_id: 100 flags: STMT_END_F                                                                   |
| binlog.000015 | 2172 | Xid            |         1 |        2203 | COMMIT /* xid=47 */                                                                               |
| binlog.000015 | 2203 | Anonymous_Gtid |         1 |        2282 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                              |
| binlog.000015 | 2282 | Query          |         1 |        2358 | BEGIN                                                                                             |
| binlog.000015 | 2358 | Table_map      |         1 |        2418 | table_id: 100 (mydb2.user)                                                                        |
| binlog.000015 | 2418 | Delete_rows    |         1 |        2470 | table_id: 100 flags: STMT_END_F                                                                   |
| binlog.000015 | 2470 | Xid            |         1 |        2501 | COMMIT /* xid=48 */                                                                               |
| binlog.000015 | 2501 | Rotate         |         1 |        2545 | binlog.000016;pos=4                                                                               |
+---------------+------+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------+
40 rows in set (0.00 sec)

15.6 bin-log恢复数据

15.6.1 准备工作
-- 刷新bin-log,生成一个新的bin-log文件,方便我们进行恢复
mysql> flush logs;

-- 创建一张新的表
mysql> create table `t_user`(`uid` int primary key, `uname` varchar(20), `age` int);
-- 插入数据若干
mysql> insert into `t_user` values (1, 'zhangsan', 18);
mysql> insert into `t_user` values (2, 'lisi', 20);
mysql> insert into `t_user` values (3, 'wangwu', 19);
mysql> insert into `t_user` values (4, 'zhaoliu', 21);
mysql> insert into `t_user` values (5, 'tianqi', 18);
-- 修改数据
mysql> update `t_user` set `age` = 20 where `uid` = 5;
-- 删除数据
mysql> delete from `t_user` where `uid` = 4;

-- 刷新bin-log,记录刚才的操作
mysql> flush logs;
15.6.2 恢复数据

我们已经进行了一些DDL、DML的操作,假如我不小心把表删除了

mysql> drop table `t_user`;

此时可以查看bin-log中的events

mysql> show binlog events in 'binlog.000017';
+---------------+------+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------------+
| Log_name      | Pos  | Event_type     | Server_id | End_log_pos | Info                                                                                                    |
+---------------+------+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------------+
| binlog.000017 |    4 | Format_desc    |         1 |         125 | Server ver: 8.0.27, Binlog ver: 4                                                                       |
| binlog.000017 |  125 | Previous_gtids |         1 |         156 |                                                                                                         |
| binlog.000017 |  156 | Anonymous_Gtid |         1 |         233 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                    |
| binlog.000017 |  233 | Query          |         1 |         399 | use `mydb2`; create table `t_user`(`uid` int primary key, `uname` varchar(20), `age` int) /* xid=431 */ |
| binlog.000017 |  399 | Anonymous_Gtid |         1 |         478 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                    |
| binlog.000017 |  478 | Query          |         1 |         554 | BEGIN                                                                                                   |
| binlog.000017 |  554 | Table_map      |         1 |         616 | table_id: 103 (mydb2.t_user)                                                                            |
| binlog.000017 |  616 | Write_rows     |         1 |         669 | table_id: 103 flags: STMT_END_F                                                                         |
| binlog.000017 |  669 | Xid            |         1 |         700 | COMMIT /* xid=432 */                                                                                    |
| binlog.000017 |  700 | Anonymous_Gtid |         1 |         779 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                    |
| binlog.000017 |  779 | Query          |         1 |         855 | BEGIN                                                                                                   |
| binlog.000017 |  855 | Table_map      |         1 |         917 | table_id: 103 (mydb2.t_user)                                                                            |
| binlog.000017 |  917 | Write_rows     |         1 |         966 | table_id: 103 flags: STMT_END_F                                                                         |
| binlog.000017 |  966 | Xid            |         1 |         997 | COMMIT /* xid=433 */                                                                                    |
| binlog.000017 |  997 | Anonymous_Gtid |         1 |        1076 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                    |
| binlog.000017 | 1076 | Query          |         1 |        1152 | BEGIN                                                                                                   |
| binlog.000017 | 1152 | Table_map      |         1 |        1214 | table_id: 103 (mydb2.t_user)                                                                            |
| binlog.000017 | 1214 | Write_rows     |         1 |        1265 | table_id: 103 flags: STMT_END_F                                                                         |
| binlog.000017 | 1265 | Xid            |         1 |        1296 | COMMIT /* xid=434 */                                                                                    |
| binlog.000017 | 1296 | Anonymous_Gtid |         1 |        1375 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                    |
| binlog.000017 | 1375 | Query          |         1 |        1451 | BEGIN                                                                                                   |
| binlog.000017 | 1451 | Table_map      |         1 |        1513 | table_id: 103 (mydb2.t_user)                                                                            |
| binlog.000017 | 1513 | Write_rows     |         1 |        1565 | table_id: 103 flags: STMT_END_F                                                                         |
| binlog.000017 | 1565 | Xid            |         1 |        1596 | COMMIT /* xid=435 */                                                                                    |
| binlog.000017 | 1596 | Anonymous_Gtid |         1 |        1675 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                    |
| binlog.000017 | 1675 | Query          |         1 |        1751 | BEGIN                                                                                                   |
| binlog.000017 | 1751 | Table_map      |         1 |        1813 | table_id: 103 (mydb2.t_user)                                                                            |
| binlog.000017 | 1813 | Write_rows     |         1 |        1864 | table_id: 103 flags: STMT_END_F                                                                         |
| binlog.000017 | 1864 | Xid            |         1 |        1895 | COMMIT /* xid=436 */                                                                                    |
| binlog.000017 | 1895 | Anonymous_Gtid |         1 |        1974 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                    |
| binlog.000017 | 1974 | Query          |         1 |        2059 | BEGIN                                                                                                   |
| binlog.000017 | 2059 | Table_map      |         1 |        2121 | table_id: 103 (mydb2.t_user)                                                                            |
| binlog.000017 | 2121 | Update_rows    |         1 |        2189 | table_id: 103 flags: STMT_END_F                                                                         |
| binlog.000017 | 2189 | Xid            |         1 |        2220 | COMMIT /* xid=437 */                                                                                    |
| binlog.000017 | 2220 | Anonymous_Gtid |         1 |        2299 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                    |
| binlog.000017 | 2299 | Query          |         1 |        2375 | BEGIN                                                                                                   |
| binlog.000017 | 2375 | Table_map      |         1 |        2437 | table_id: 103 (mydb2.t_user)                                                                            |
| binlog.000017 | 2437 | Delete_rows    |         1 |        2489 | table_id: 103 flags: STMT_END_F                                                                         |
| binlog.000017 | 2489 | Xid            |         1 |        2520 | COMMIT /* xid=438 */                                                                                    |
| binlog.000017 | 2520 | Rotate         |         1 |        2564 | binlog.000018;pos=4                                                                                     |
+---------------+------+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------------+
40 rows in set (0.00 sec)

可以看到每一个Event的Pos信息,那么我们就可以通过Pos信息恢复数据

# --start-position: 指定起始的事件位置,如果不指定,默认从头开始
# --stop-position: 指定结束的事件位置,如果不指定,默认到结尾
# --start-datetime: 指定起始的事件时间,如果不指定,默认从头开始
# --stop-datetime: 指定结束的事件时间,如果不指定,默认到结尾

mysqlbinlog --stop-position=2489 --database=mydb2 binlog.000017 | mysql -uroot -p123456

可以看到数据都恢复啦!

你可能感兴趣的:(全链路数据仓库,mysql,数据库,bin-log,mysql的bin-log,bin-log日志)