【Binlog实战】:基于Spring监听Binlog日志
binlog的三种模式
-
MySQL 的二进制日志(binlog)有三种不同的格式,通常被称为 binlog 模式。这三种模式分别是 Statement 模式、Row 模式和Mixed 模式。
-
Statement 模式:
- 在 Statement 模式下,MySQL 记录每个会更改数据的 SQL 语句。
- binlog 记录的是执行的 SQL 语句本身,而不是具体的数据变化。
- 例如,如果执行了
UPDATE
语句,binlog 记录的是这个UPDATE
语句的文本。
-
Row 模式:
- 在 Row 模式下,MySQL 记录每一行数据的变化。
- binlog 记录的是行数据的变化,而不是 SQL 语句。
- 例如,如果执行了
UPDATE
语句,binlog 记录的是被修改的行的实际数据。
-
Mixed 模式:
- Mixed 模式是 Statement 模式和 Row 模式的结合。
- 在 Mixed 模式下,MySQL 根据执行的 SQL 语句的类型来决定是记录语句还是记录行。
- 通常,对于简单的语句,使用 Statement 模式,对于涉及到行变化的复杂语句,使用 Row 模式。
-
这些模式可以通过 MySQL 配置文件中的
binlog_format
参数进行配置。例如: -
[mysqld] binlog_format=mixed
-
其中,
statement
、row
和mixed
分别代表 Statement 模式、Row 模式和 Mixed 模式。选择适当的 binlog 模式取决于应用的特定需求和性能要求。不同的模式具有不同的优劣势,例如,Statement 模式可能会更轻量,而 Row 模式可能提供更详细的数据变化信息。
以Mixed 为例
-
查看binlog是否开启
-
show variables like '%log_bin%'
-
启动springboot程序
-
新建数据库
-
这个事件是一个 binlog 事件,其内容表示一个 SQL 查询事件。让我解释一下这个事件的各个部分:
- 事件类型 (***
eventType
***): 该事件的类型是QUERY
,表示这是一个 SQL 查询事件。 - 时间戳 (***
timestamp
***): 事件的时间戳为1700045267000
,表示事件发生的时间。 - 线程ID (***
threadId
***): 线程ID 是189
,表示执行这个查询的线程的标识符。 - 执行时间 (***
executionTime
***): 执行时间为0
,表示执行这个查询所花费的时间。 - 错误代码 (***
errorCode
***): 错误代码为0
,表示查询执行没有错误。 - 数据库 (***
database
***): 数据库为test2023
,表示这个查询发生在test2023
数据库中。 - SQL 查询 (***
sql
***): 实际的 SQL 查询为CREATE DATABASE
test2023CHARACTER SET utf8 COLLATE utf8_general_ci
,表示执行了创建数据库的操作。 - 这个事件的作用是在
test2023
数据库中执行了一个创建数据库的 SQL 查询。这是 binlog 中的一部分,用于记录数据库中的变化,以便进行数据备份、主从同步等操作。
- 事件类型 (***
-
新建表数据
-
CREATE TABLE `t_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`userName` varchar(100) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
-
这个事件也是一个 binlog 事件,表示一个 SQL 查询事件。让我解释一下这个事件的各个部分:
- 事件类型 (***
eventType
***): 该事件的类型是QUERY
,表示这是一个 SQL 查询事件。 - 时间戳 (***
timestamp
***): 事件的时间戳为1700045422000
,表示事件发生的时间。 - 线程ID (***
threadId
***): 线程ID 是204
,表示执行这个查询的线程的标识符。 - 执行时间 (***
executionTime
***): 执行时间为0
,表示执行这个查询所花费的时间。 - 错误代码 (***
errorCode
***): 错误代码为0
,表示查询执行没有错误。 - 数据库 (***
database
***): 数据库为test2023
,表示这个查询发生在test2023
数据库中。 - SQL 查询 (***
sql
***): 实际的 SQL 查询为CREATE TABLE
t_user(
idbigint(20) NOT NULL AUTO_INCREMENT,
userNamevarchar(100) NOT NULL, PRIMARY KEY (
id) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4
,表示执行了在test2023
数据库中创建名为t_user
的表的操作。 - 这个事件的作用是在
test2023
数据库中创建了一个名为t_user
的表,该表包含id
和userName
两个字段,其中id
是自增的主键。这种类型的事件常常用于记录数据库结构的变化,以便进行数据备份、迁移和版本控制等操作。
- 事件类型 (***
-
插入表数据
-
INSERT INTO `test2023`.`t_user` (`id`, `userName`) VALUES("10086","用心记录技术,走心分享,始于后端,不止于后端,励志成为一名优秀的全栈架构师,真正的实现码中致富。");
-
这个事件也是一个 binlog 事件,表示一个 SQL 查询事件,具体如下:
- 事件类型 (***
eventType
***): 该事件的类型是QUERY
,表示这是一个 SQL 查询事件。 - 时间戳 (***
timestamp
***): 事件的时间戳为1700045547000
,表示事件发生的时间。 - 线程ID (***
threadId
***): 线程ID 是204
,表示执行这个查询的线程的标识符。 - 执行时间 (***
executionTime
***): 执行时间为0
,表示执行这个查询所花费的时间。 - 错误代码 (***
errorCode
***): 错误代码为0
,表示查询执行没有错误。 - 数据库 (***
database
***): 数据库为test2023
,表示这个查询发生在test2023
数据库中。 - SQL 查询 (***
sql
***): 实际的 SQL 查询为INSERT INTO
test2023.
t_user(
id,
userName) VALUES ( "10086", "用心记录技术,走心分享,始于后端,不止于后端,励志成为一名优秀的全栈架构师,真正的实现码中致富。"
,表示执行了向test2023
数据库的t_user
表中插入一行数据
- 事件类型 (***
-
这个事件的作用是向
t_user
表中插入了一行数据,包含了id
和userName
两个字段的值。这种类型的事件通常用于记录数据的变化,以便进行数据备份、同步和迁移等操作。 -
修改表数据
-
UPDATE `test2023`.`t_user` SET `id` = '10086',`userName` = '我的修改数据!!!' WHERE(`id` = '10086');
-
这个事件同样是一个 binlog 事件,表示一个 SQL 查询事件,具体如下:
- 事件类型 (***
eventType
***): 该事件的类型是QUERY
,表示这是一个 SQL 查询事件。 - 时间戳 (***
timestamp
***): 事件的时间戳为1700045675000
,表示事件发生的时间。 - 线程ID (***
threadId
***): 线程ID 是204
,表示执行这个查询的线程的标识符。 - 执行时间 (***
executionTime
***): 执行时间为0
,表示执行这个查询所花费的时间。 - 错误代码 (***
errorCode
***): 错误代码为0
,表示查询执行没有错误。 - 数据库 (***
database
***): 数据库为test2023
,表示这个查询发生在test2023
数据库中。 - SQL 查询 (***
sql
***): 实际的 SQL 查询为UPDATE
test2023.
t_userSET
id= '10086',
userName= '我的修改数据!!!' WHERE (
id= '10086')
,表示执行了更新test2023
数据库中的t_user
表中一行数据的操作。
- 事件类型 (***
-
这个事件的作用是将
t_user
表中id
为10086
的行的数据进行更新,将id
修改为10086
,userName
修改为 ‘我的修改数据!!!’。这种类型的事件通常用于记录数据的变化,以便进行数据备份、同步和迁移等操作。 -
删除表数据
-
DELETE FROMt_user WHEREid = '10086';
-
这个事件同样是一个 binlog 事件,表示一个 SQL 查询事件,具体如下:
- 事件类型 (***
eventType
***): 该事件的类型是QUERY
,表示这是一个 SQL 查询事件。 - 时间戳 (***
timestamp
***): 事件的时间戳为1700045755000
,表示事件发生的时间。 - 线程ID (***
threadId
***): 线程ID 是204
,表示执行这个查询的线程的标识符。 - 执行时间 (***
executionTime
***): 执行时间为0
,表示执行这个查询所花费的时间。 - 错误代码 (***
errorCode
***): 错误代码为0
,表示查询执行没有错误。 - 数据库 (***
database
***): 数据库为test2023
,表示这个查询发生在test2023
数据库中。 - SQL 查询 (***
sql
***): 实际的 SQL 查询为DELETE FROM t_user WHERE id = '10086'
,表示执行了删除test2023
数据库中的t_user
表中一行数据的操作。
- 事件类型 (***
-
这个事件的作用是删除
t_user
表中id
为10086
的行。这种类型的事件通常用于记录数据的删除操作,以便进行数据备份、同步和迁移等操作。 -
总结: binlog_format 设置为 mixed 时,对于 INSERT、UPDATE 和 DELETE 操作,它们在 binlog 中的事件类型都会被表示为 QUERY 事件。这是因为在 mixed 模式下,MySQL 使用了不同的方式来记录不同类型的操作,但在 binlog 中,它们都被包装成了 QUERY 事件。
-
在 mixed 模式下:
- 对于某些语句级别的操作(例如非确定性的语句或不支持事务的存储引擎),会使用 STATEMENT 事件。
- 对于其他一些情况,会使用 ROW 事件,将变更的行作为事件的一部分进行记录。
-
这就是为什么看到的 INSERT、UPDATE 和 DELETE 操作的事件类型都是 QUERY。在处理这些事件时,需要根据具体的 SQL 查询语句或其他信息来确定操作的类型。