当前位置: 首页 > news >正文

通过Java监听MySQL数据的变化

文章目录

    • 实现Java监听MySQL数据是否发生变化
      • 原理
      • 开启MySQL的binlog功能
      • Java监听MySQL的binlog实现监听数据变化

实现Java监听MySQL数据是否发生变化

原理

原理:java通过bin-log监控mysql数据变化
binlog :binlog 就是binary log,二进制日志文件,这个文件记录了mysql所有的增、删、改语句。通过binlog日志我们可以做数据恢复,做主从复制等等。可以看到,只要有了这个binlog,我们就拥有了mysql的完整备份了。
就是说一旦开启了这个功能,数据库中数据的任何变化,都会记录到这种日志文件中,所以可以通过Java监听这种的文件,来监听MySQL数据的变化。

开启MySQL的binlog功能

首先,需要开启MySQL的binlog功能,MySQL默认是未开启的
查询是否开始binlog功能的sql语句:show variables like ‘%log_bin%’ ;
log_bin的值是no则表示开启,我也不知道没开启是没有这个还是值是off,我也不敢瞎说
开启分为两步,1.改配置 2.重启MySQL服务

改配置
打开自己MySQL的配置文件,比如PC端的即my.ini文件,加上下面三句

log-bin=mysql-bin #[必须]启用二-进制日志
server-id=100 #[必须]服务器唯一ID,如果是用于多台MySQL,ID不要重复就行
binlog-format = ROW #这句也得加,下面解释

改完,然后重启MySQL服务就可以了
说明:
mysql-bin只是个名字而已,可以随便起。将来保存的日志文件名就是mysql-bin.000001,mysql-bin.000002这样的。生成的日志文件会存放在自己的MySQL的存放数据的文件夹,比如我设置的存放MySQL数据的文件夹目录是:D:\MySql\mysql-8.0.24\data\,然后生成的日志文件就会在这个目录下。
binlog-format = ROW,binlog_format 设置为 ROW可以保证数据的一致, 因为在 STATEMENT 或 MIXED 模式下, Binlog 只会记录和传输 SQL 语句(以减少日志大小),而不包含具体数据,我们也就无法保存了。

Java监听MySQL的binlog实现监听数据变化

Java需要使用一个工具mysql-binlog-connector-java
导入Jar包:
这个Jar包有两个版本,一个是com.github.shyiko的一个是com.zendesk,使用方式和代码完全一样,只是各自的实现方式可能不同,但是com.github.shyiko20年停止更新了,对于MySQL8兼容性不是很好,建议使用com.zendesk。

        <dependency>
            <groupId>com.zendesk</groupId>
            <artifactId>mysql-binlog-connector-java</artifactId>
            <version>0.27.1</version> <!--2022.09.17版的-->
        </dependency>

顺便附上com.github.shyiko
在这里插入图片描述
MySQL8及以上使用com.github.shyiko的可能会出现Client does not support authentication protocol requested by server...错误
原因:mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password,
解决办法:把mysql用户登录密码加密规则还原成mysql_native_password,
SQL语句:ALTER USER 'root'@'自己需要连接的数据库的host,自己本机的就用localhost' IDENTIFIED WITH mysql_native_password BY '自己所使用的登录密码';
然后就好了

然后再看逻辑代码:
实现是在connectMysqlBinLog()方法中的,里面通过data instanceof ****,即可查询到执行的增删改什么请求,详细请看代码,看一下就明白了

//为什么甚至路径都一样,还是com.github.shyiko.***,
// 因为com.zendesk这个包,里面包了个com.github.shyiko.***这玩意,我怀疑是收购关系
import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
//在SpringBoot中,提供了一个接口:ApplicationRunner。
//该接口中,只有一个run方法,他执行的时机是:spring容器启动完成之后,就会紧接着执行这个接口实现类的run方法。
public class MysqlBinLogClient implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        //项目启动完成连接bin-log
        new Thread(() -> {
            connectMysqlBinLog();
        }).start();

    }

    /**
     * 连接mysqlBinLog
     */
    public void connectMysqlBinLog() {
        //自己MySQL的信息。host,port,username,password
        BinaryLogClient client = new BinaryLogClient("localhost", 3306, "root", "root"); 
        client.setServerId(100); //和自己之前设置的server-id保持一致,但是我不知道为什么不一致也能成功

        client.registerEventListener(event -> {
            EventData data = event.getData();
            if (data instanceof TableMapEventData) {
                TableMapEventData tableMapEventData = (TableMapEventData) data;
                System.out.print("TableID:");
                System.out.println(tableMapEventData.getTableId());
                System.out.print("TableName:");
                System.out.println(tableMapEventData.getTable());
            }
            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());
            }
        });

        try {
            client.connect();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

相关文章:

  • Sam-ba烧录工具的使用教程
  • 基于驾驶训练优化算法的函数寻优算法
  • Linux运维面试题总结—Linux基础、计算机网络基础
  • ARM通用中断控制器GIC之中断处理
  • Vector简介说明
  • 图像处理黑科技——弯曲矫正、去摩尔纹、切边增强、PS检测
  • 大学网课查题接口
  • 【C语言】扫雷小游戏
  • 『Halcon与C#混合编程』011_工业相机的SDK介绍
  • 卷积核flip+transpose+cv.imread+enumerate+np.pad+tqdm
  • 【第一阶段:java基础】第1章:java概述
  • MySQL进阶之触发器、锁、InnoDB引擎和MySQL管理
  • 【Linux】虚拟机安装Ubuntu后的一些通用设置
  • [Android]使用Android打包Unity工程
  • 【STM32】PWM输出
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 2017 前端面试准备 - 收藏集 - 掘金
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • ES2017异步函数现已正式可用
  • Java 内存分配及垃圾回收机制初探
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • Laravel 中的一个后期静态绑定
  • nodejs调试方法
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 开源SQL-on-Hadoop系统一览
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 我的面试准备过程--容器(更新中)
  • 我这样减少了26.5M Java内存!
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • #Linux(Source Insight安装及工程建立)
  • #单片机(TB6600驱动42步进电机)
  • (2)STL算法之元素计数
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (libusb) usb口自动刷新
  • (层次遍历)104. 二叉树的最大深度
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (分布式缓存)Redis分片集群
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (转)我也是一只IT小小鸟
  • .net core 6 redis操作类
  • .NET Core WebAPI中封装Swagger配置
  • .NET gRPC 和RESTful简单对比
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .net快速开发框架源码分享
  • [C++11 多线程同步] --- 条件变量的那些坑【条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)】
  • [DM复习]关联规则挖掘(下)
  • [LeetCode] Longest Common Prefix 字符串公有前序