Database Change Notification
应用端对于数据变更通知是有着较多需求场景的,例如数据更新后的提醒、预警;web 端展现数据对于实时性的要求等。大部分产品对于数据库中数据变更信息的获取只能通过轮询的方式实现,轮询的时间间隔太短会有性能问题,太长会损害实时性。因此,考虑实现数据库中数据变更后主动向应用程序发送通知,针对不同的数据库都有哪些可用方案呢?
Oracle Database
适用范围
表级别的增、删或改通知,例如,针对数据库表 A 有变更通知, 那么 A 中发生的增、删或改 都会通知,不能具体到某个字段或者某条记录,需要在被通知端判断。
MySQL
UDF + Trigger
使用的是 MySQL 的用户自定义函数 User-Defined Functions;
A user-defined function (UDF) is a way to extend MySQL with a new function that works like a native (built-in) MySQL function such as ABS() or CONCAT().
For the UDF mechanism to work, functions must be written in C or C++ (or another language that can use C calling conventions), your operating system must support dynamic loading and you must have compiled mysqld dynamically (not statically).
UDF 是一种 MySQL 扩展,自定义一个类似原生内置的函数,可以被同样使用。为了能达到这样的效果,这种函数必须使用能被 C 语言调用的语言编写,并且编译成动态链接库。Linux 上是 .so 文件,Windows 上是 .dll 文件。
我们使用这个 mysql-udf-http 来实现发送通知的效果,一个开源项目,8年多没人维护了。这是中文说明 使用说明。
我在 Ubuntu 上安装的 MySQL ,再编译这个东西 是可以成功使用的。Windows 上没有尝试,应该也可以,只不过编译起来稍微麻烦一些。
MySQL 的触发器 create-trigger 可以在 数据的增、删、改前后触发 trigger_body 的执行,可以执行多条 SQL 语句。
例如:
1 | //创建Trigger |
其实就是触发器触发一下我们自定义的函数,向指定的接口发送一个请求,通知到应用层面数据被修改、新增、删除。
UDF+Trigger 适用范围
触发器针对的是表,每一行的变动都能被检测到;不能只监测指定字段的变动。
针对不同的平台,linux、windows 需要分别编译动态链接库,复制到MySQL插件文件夹下。
需要创建函数,创建触发器的权限。
如果数据变更非常频繁,那么会向指定的接口发送很多的请求,不知道web服务会不会挂。
触发器尽量简单只有一个,防止对数据库性能产生过多的影响。
表级别的增、删或改通知,例如,针对数据库表 A 有变更通知, 那么 A 中发生的增、删或改 都会通知,不能具体到某个字段或者某条记录,需要在被通知端判断。
binlog
原理
数据库为了主从复制结构和容灾,都会有一份提交日志 (commit log),通过解析这份日志,理论上说可以获取到每次数据库的数据更新操作。
以下皆以 MySQL 为例:
两种方式获取 MySQL bin-log 的方式:
- 如果是同一台主机,那么直接使用获取本地文件即可解析;
- 如果是远程,那么可以通过 MySQL master 和 slave 的结构,伪装成一个 slave 来获取 master 的 bin-log 来解析。
上面那篇文章介绍的比较复杂,是关于集群数据同步的解决方案,我们不需要那么复杂,只需要当数据发生变更时解析到变更通知到应用即可。
协议解析方案
时至今日, 已经有很多大厂开源了自己的 MySQL binlog 解析方案,Java 语言可选的有:
想自己造轮子实现协议的,也可以参考 MySQL 官方文档
demo
一个使用 mysql-binlog-connector-java 的 demo。
- 修改 MySQL 配置 my.cnf(Linux)或者my.ini(Windows)
1 | [mysqld] |
为了防止权限混乱,一般都是建立一个单独用于复制的账户。
1 | create user rep; |
需重启数据库服务。
- Tapping into MySQL replication stream
1 | BinaryLogClient client = new BinaryLogClient("192.168.1.123", |
1 | connect success |
Binlog 适用范围
- 监控整个数据库,不针对单个表或者字段,需要自己在代码中判断;
- 删除、修改、添加都能够监听到。
大部分数据库变更通知都是基于数据库同步服务的,因此最细的角度就是表级别,不能到具体的字段或者记录,需要在被同步端也就是被通知端自行判断。
扩展方案
其他参考
Author: yaohwu
Link: https://notes.yaohwu.xyz/2018/02/03/database-change-notification/
License: 知识共享署名-非商业性使用 4.0 国际许可协议