首頁 > 軟體

如何通過Java監聽MySQL資料的變化

2023-03-15 06:02:12

原理

原理: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的值是on則表示開啟,我也不知道沒開啟是沒有這個還是值是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:MySqlmysql-8.0.24data,然後生成的紀錄檔檔案就會在這個目錄下。

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 lombok.extern.slf4j.Slf4j;

import java.io.IOException;

//此類可以監控MySQL庫資料的增刪改
@Component
@Slf4j  //用於列印紀錄檔
//在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() {
        log.info("監控BinLog服務已啟動");

        //自己MySQL的資訊。host,port,username,password
        BinaryLogClient client = new BinaryLogClient("localhost", 3306, "root", "root");
        /**因為binlog不是以資料庫為單位劃分的,所以監控binglog不是監控的單個的資料庫,而是整個當前所設定連線的MySQL,
         *其中任何一個庫發生資料增刪改,這裡都能檢測到,
         *所以不用設定所監控的資料庫的名字(我也不知道怎麼設定,沒發現有包含這個形參的建構函式)
         *如果需要只監控指定的資料庫,可以看後面程式碼,可以獲取到當前發生變更的資料庫名稱。可以根據名稱來決定是否監控
         **/

        client.setServerId(100); //和自己之前設定的server-id保持一致,但是我不知道為什麼不一致也能成功

//下面直接照抄就行
        client.registerEventListener(event -> {
            EventData data = event.getData();
            if (data instanceof TableMapEventData) {
                //只要連線的MySQL發生的增刪改的操作,則都會進入這裡,無論哪個資料庫

                TableMapEventData tableMapEventData = (TableMapEventData) data;

                //可以通過轉成TableMapEventData類範例的tableMapEventData來獲取當前發生變更的資料庫
                System.out.println("發生變更的資料庫:"+tableMapEventData.getDatabase());

                System.out.print("TableID:");
                //表ID
                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();
        }

    }
}

有一定可能資料發生變更後控制檯沒列印,可能是載入慢的原因,稍等一會控制檯就可能會列印相關資訊

總結

到此這篇關於如何通過Java監聽MySQL資料的變化的文章就介紹到這了,更多相關Java監聽MySQL資料變化內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com