此博客用于个人学习,来源于网上,对知识点进行一个整理。
1.MySQL Binlog 介绍:
1.1 简介:
1)什么是 Binlog?
Mysql binlog 是二进制日志文件,用于记录 mysql 的数据更新或者潜在更新(比如 DELETE 语句执行删除而实际并没有符合条件的数据)的 SQL 语句,并以二进制的形式保存在磁盘中,在 mysql 主从复制中就是依靠的 binlog。
2)Binlog 的作用是什么?
有两个主要的作用:复制(主从同步),恢复和审计。
3)Binlog 相关的变量:
变量名称 | 变量含义 | 相关语句 |
---|---|---|
log_bin | Binlog 开关 | 查看变量:show variables like ‘log_bin’; |
log_format | Binlog 日志的格式 | 查看变量:show variables like ‘log_format’; |
4)binlog 的三种工作模式:
工作类型 | 简介 |
---|---|
Row level | 日志中会记录每一行数据被修改的情况,然后在 slave 端对相同的数据进行修改。优点:能清楚的记录每一行数据修改的细节。缺点:数据量太大 |
Statement level | 每一条被修改数据的 sql 都会记录到 master 的 bin-log 中,slave 在复制的时候 sql 进程会解析成和原来 master 端执行过的相同的 sql 再次执行。在主从同步中一般是不建议用 statement 模式的,因为会有些语句不支持,比如语句中包含 UUID 函数,以及 LOAD DATA IN FILE 语句等。优点:解决了 Row level 下的缺点,不需要记录每一行的数据变化,减少 bin-log 日志量,节约磁盘 IO,提高性能。缺点:容易出现主从复制不一致 |
Mixed | 结合了 Row level 和 Statement level 的优点,同时 binlog 结构也更复杂 |
5)管理 Binlog 相关的 SQL 语句:
SQL 语句 | 语义含义 |
---|---|
show master logs; | 查看所有 Binlog 的日志列表 |
show master status; | 查看最后一个 Binlog 日志的编号名称,及最后一个事情结束的位置(pos) |
flush logs; | 刷新 Binlog,此刻开始产生一个新编号的 Binlog 日志文件 |
reset master; | 清空所有的 Binlog 日志 |
6)查看 Binlog 相关的 SQL 语句:
(show binlog events [IN ‘log_name’])[FROM pos] [LIMT [offset,] row_count])
SQL 语句 | 语句含义 |
---|---|
show binlog events; | 查看第一个 Binlog 日志 |
show binlog events in ‘binlog.000030’; | 查看指定的 Binlog 日志 |
show binlog events in ‘binlog.000030’ from 931; | 从指定的位置开始 |
show binlog events in ‘binlog.000030’ from 931 limit 2; | 从指定的位置开始,查看指定的 Binlog 日志,限制查询的条数 |
show binlog events in ‘binlog.000030’ from 931 limit 1,2; | 从指定的位置开始,带有偏移,查看指定的 Binlog 日志,限制查询的条数 |
6)Binlog 中的 Event_type:
Event_type | 含义 |
---|---|
QUERY_EVENT | 与数据无关的操作,begin、drop table、truncate table 等 |
TABLE_MAP_EVENT | 记录下一个操作所对应的表信息,存储了数据库名和表名 |
XID_EVENT | 标记事务提交 |
WRITE_ROWS_EVENT | 插入数据,即 insert 操作 |
UPDATE_ROWS_EVENT | 更新数据,即 update 操作 |
DELETE_ROWS_EVENT | 删除数据,即 delete 操作 |
1.2 使用 Binlog 监听示例:
在 ad-search 中,定义一个测试类,用于使用 Binlog 监听,当我们使用索引操作的时候,就会打印在控制台中i。
public class BinlogServiceTest {
public static void main(String[] args) throws Exception{
BinaryLogClient client = new BinaryLogClient(
"127.0.0.1",
3306,
"root",
"root"
);
client.registerEventListener(event -> {
EventData data = event.getData();
if (data instanceof UpdateRowsEventData) {
System.out.println("Update--------------");
System.out.println(data.toString());
} else if (data instanceof WriteRowsEventData) {
System.out.println("Write---------------");
System.out.println(data.toString());
} else if (data instanceof DeleteRowsEventData) {
System.out.println("Delete--------------");
System.out.println(data.toString());
}
});
client.connect();
}
}
2. 模板文件操作:
之前使用 Binlog 去监听索引的增量数据,是为了使我们的检索服务和投放系统实现聚焦。投放系统在不停的工作中,广告主有可能会对之前网络数据的一些增删改进行操作。投放系统与检索系统尽量不存在耦合关系,所以我们主动去监听写入 MySQL 的 Binlog,然后去解析 Binlog,去得到增量数据,实现更新。由于我们的检索服务没有去定义各个数据库和数据表,所以我们需要定义一份模板文件,通过解析模板文件得到我们需要的数据库和数据表。因为 MySQL 的 Binlog 是不关心具体是哪个数据库还是哪个数据表发生变化,它对于所有的数据库和数据表发生变化都会记录在 Binlog 里面,所以我们需要一份文件去指明我们需要监听的那一部分是什么。
2.1 构造解析 Binlog 使用到的模板文件:
首先定义一个 JsonTable 类,对模板文件中的表进行表达。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JsonTable {
//表的名字
private String tableName;
//层级
private Integer level;
private List<Column> insert;
private List<Column> update;
private List<Column> delete;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Column {
private String column;
}
}
定义一个 Template 类表达整个模板文件,表面我们要去解析 Binlog 的哪些部分。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Template {
private String database;
private List<JsonTable> tableList;
}
定义一个 TableTemplate 类方便未来操作时读取表的一些信息。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TableTemplate {
private String tableName;
private String level;
private Map<OpType