一个二进制日志,用来记录对数据发生或潜在发生更改的SQL语句,并以而进行的形式保存在磁盘中。
binlog 的作用?
最主要有3个用途:
数据复制(主从同步)
Mysql 的Master-Slave协议,让Slave可以通过监听binlog实现数据复制,达到数据一致性目的
数据恢复
通过MYSQLbinlog工具恢复数据
增量备份
Binlog 变量
log_bin (Binlog 开关,使用show variables like 'log_bin';查看)
binlog_format (Binlog 日志格式,使用show variables like 'binlog_format';查看)
日志格式总共有三种:
ROW, 仅保存记录被修改的细节,不记录SQL语句上下文相关信息。(能清晰的记录下每行数据的修改细节,不需要记录上下文相关信息,因此不会发生某些特定情况下的procedure、function以及trigger 的调用无法被准确复制的问题,任何情况下都可以被复制,且能加快从库重放日志的效率,保证从库数据的一致性)
STATEMENT,每一条修改数据的SQL都会被记录。(只记录执行语句的细节和上下文环境,避免了记录每一行的变化,在一些修改记录较多的情况下,相比ROW类型能大大减少binlog的日志量,节约IO,提高性能。还可以用于实时的还原,同时主从版本可以不一样,从服务器版本可以比主服务器版本高)
MIXED, 上述2种的混合使用
Binlog 管理
show master logs; 查看所有binlog的日志列表
show master status; 查看最后一个binlog日志编号名称,以及最后一个事件技术的位置(position)
Flush logs; 刷新binlog,此刻开始产生一个新编号的binlog日志文件
reset master; 清空所有的binlog日志
Binlog 相关SQL show binlog events[in 'log_name'][from position][limit [offset,]row_count]
常用的Binlog event
QUERY - 与数据无关的操作,begin、drop table、truncate table等等
TABLE_MAP - 记录下一个操作所对应的表信息,存储了数据库名称和表名称
XID - 标记事务提交
WRITE_ROWS 插入数据,即insert操作
UPDATE_ROWS 更新数据,即update操作
DELETE_ROWS 删除数据,即delete操作
Event包含header和data两部分,header提供了event的创建时间,哪个服务器等信息,data部分提供的是针对该event的具体信息,如具体数据的修改。
Tip: binlog不会记录数据表的列名
在接下来的实现中,我们会将自己的系统包装成一个假的Mysql Slave,通过开源工具mysql-binlog-connector-java来实现监听binlog。
开源工具mysql-binlog-connector-java
工具源码:Github传送门
组件使用
1.加依赖
<!-- binlog 日志监听,解析开源工具类库 --> <dependency> <groupId>com.github.shyiko</groupId> <artifactId>mysql-binlog-connector-java</artifactId> <version>0.18.1</version> </dependency>2.创建一个测试接口
package com.sxzhongf.ad.service; import com.github.shyiko.mysql.binlog.BinaryLogClient; import com.github.shyiko.mysql.binlog.event.DeleteRowsEventData; import com.github.shyiko.mysql.binlog.event.EventData; import com.github.shyiko.mysql.binlog.event.UpdateRowsEventData; import com.github.shyiko.mysql.binlog.event.WriteRowsEventData; import java.io.IOException; /** * BinlogServiceTest for 测试Mysql binlog 监控 * {@code * Mysql8 连接提示 Client does not support authentication protocol requested by server; consider upgrading MySQL client 解决方法 * USE mysql; * ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; * FLUSH PRIVILEGES; * } * * @author <a href="http://www.yisu.com/zixun/mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a> */ public class BinlogServiceTest { /** * --------Update----------- * UpdateRowsEventData{tableId=90, includedColumnsBeforeUpdate={0, 1, 2, 3, 4, 5, 6, 7}, includedColumns={0, 1, 2, 3, 4, 5, 6, 7}, rows=[ * {before=[11, 10, Test Bin Log, 1, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019], after=[11, 10, zhangpan test Binlog, 1, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019]} * ]} * * --------Insert----------- * WriteRowsEventData{tableId=91, includedColumns={0, 1, 2, 3, 4, 5, 6, 7}, rows=[ * [10, 11, ad unit test binlog, 1, 0, 1236.7655, Thu Jun 27 08:00:00 CST 2019, Thu Jun 27 08:00:00 CST 2019] * ]} */ public static void main(String[] args) throws IOException { // //构造BinaryLogClient,填充mysql链接信息 BinaryLogClient client = new BinaryLogClient("127.0.0.1", 3306, "root", "12345678" ); //设置需要读取的Binlog的文件以及位置,否则,client会从"头"开始读取Binlog并监听 // client.setBinlogFilename("binlog.000035"); // client.setBinlogPosition(); //给客户端注册监听器,实现对Binlog的监听和解析 //event 就是监听到的Binlog变化信息,event包含header & data 两部分 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("--------Insert-----------"); System.out.println(data.toString()); } else if (data instanceof DeleteRowsEventData) { System.out.println("--------Delete-----------"); System.out.println(data.toString()); } }); client.connect(); } }运行:
八月 08, 2019 9:13:32 上午 com.github.shyiko.mysql.binlog.BinaryLogClient connect 信息: Connected to 127.0.0.1:3306 at binlog.000038/951 (sid:65535, cid:336) ...执行sql update ad_user set user_status=1 where user_id=10;
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。