通过Nodejs和二进制日志实时监视MySQL数据更改
您可能希望捕获MySQL数据表中的更改,以通知应用程序或发送电子邮件,而无需更改先前的代码库。
我曾经有一个用例,网上没有什么可以帮助您的,所以在谷歌搜索并尝试了几个小时后,我遇到了一个名为“ mysql-events ”的库,该库监视MySQL的二进制日志。
二进制日志包含描述数据库更改(例如表创建操作或表数据更改)的“事件”。它还包含针对可能进行了更改的语句的事件(例如,
[DELETE](https://dev.mysql.com/doc/refman/8.0/en/delete.html)
不匹配任何行),除非使用基于行的日志记录。二进制日志还包含有关每个语句花费该更新数据多长时间的信息。二进制日志有两个重要目的:对于复制,主复制服务器上的二进制日志提供了要发送到从属服务器的数据更改的记录。主服务器将其二进制日志中包含的事件发送到其从属服务器,从属服务器执行这些事件以对主服务器进行相同的数据更改。
某些数据恢复操作需要使用二进制日志。还原备份后,将重新执行在执行备份后记录的二进制日志中的事件。这些事件使数据库从备份开始就保持最新状态。
— —来源
在开始之前,我们需要通过my.ini
在Windows和my.cnf
ubuntu中更改文件来启用MySQL中的二进制日志。
- 根据安装mysql的方式,这些文件的位置可能有所不同。
我们需要 在mysqld部分下添加以下行,然后重新启动mysql。
log-bin=bin.log
log-bin-index=bin-log.index
max_binlog_size=100M
binlog_format=row
socket=mysql.sock
现在,NodeJs脚本非常简单,这要归功于“ mysql-events ”。
- 我将从一个空目录开始,然后键入
npm init -y
。 npm i @rodrigogs/mysql-events
- 我将创建一个index.js文件,该文件监视mysql二进制日志事件。
- 我将保持非常简单,因为您可以自行处理事件,通过console.log记录事件就足够了。
在MySQL 8+中,默认情况下启用二进制日志。
const mysql = require('mysql');
const MySQLEvents = require('@rodrigogs/mysql-events');
const ora = require('ora'); // cool spinner
const spinner = ora({
text: '🛸 Waiting for database events... 🛸',
color: 'blue',
spinner: 'dots2'
});
const program = async () => {
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root'
});
const instance = new MySQLEvents(connection, {
startAtEnd: true // to record only the new binary logs, if set to false or you didn'y provide it all the events will be console.logged after you start the app
});
await instance.start();
instance.addTrigger({
name: 'monitoring all statments',
expression: 'TEST.*', // listen to TEST database !!!
statement: MySQLEvents.STATEMENTS.ALL, // you can choose only insert for example MySQLEvents.STATEMENTS.INSERT, but here we are choosing everything
onEvent: e => {
console.log(e);
spinner.succeed('👽 _EVENT_ 👽');
spinner.start();
}
});
instance.on(MySQLEvents.EVENTS.CONNECTION_ERROR, console.error);
instance.on(MySQLEvents.EVENTS.ZONGJI_ERROR, console.error);
};
program()
.then(spinner.start.bind(spinner))
.catch(console.error);
上面代码的结果:
- 我有一个名为TEST的数据库和一个名为test_table的表(名称:varchar(50),age int)
-
插入时:
SQL是INSERT INTO test_table VALUES('rowad',1)
- 更新时:
SQL是UPDATE test_table SET age = 3 WHERE age = 1;
,并且有5行
- 删除时:
SQL是“ DELETE test_table;”,它删除了所有19行
当我需要使用网络套接字实时更新某些UI或使用消息广播工具(例如Redis的Pub / Sub或RabbitMQ Pub / Sub)调用另一个应用程序时,我发现这非常有用。
希望对您有帮助。
参考
Monitoring MySQL data changes in Real-time via Nodejs & binary logs