使用 binlog 实时监控 Mysql 数据更新

Posted by Masutangu on March 8, 2016

上一篇文章《UDF+Trigger实时监控Mysql数据更新》介绍了用UDF+Trigger的方式来监控Mysql数据的更新,这次介绍下使用binlog监控数据更新的方法。

binlog 简介

The binary log is a set of log files that contain information about data modifications made to a MySQL server instance.

其主要有以下两个用途:

  • 主从同步

  • 数据恢复

mysql主从同步原理 利用binlog来监控mysql数据的更新,以更新缓存。原理类似于mysql的主从同步。先简单介绍下mysql主从同步的原理:

  • Whenever the master’s database is modified, the change is written to a file, the so-called binary log, or binlog. This is done by the client thread that executed the query that modified the database.
  • The master has a thread, called the dump thread, that continuously reads the master’s binlog and sends it to the slave.
  • The slave has a thread, called the IO thread, that receives the binlog that the master’s dump thread sent, and writes it to a file: the relay log.
  • The slave has another thread, called the SQL thread, that continuously reads the relay log and applies the changes to the slave server.

利用binlog监听mysql更新

我们的目的是监听mysql数据变化,及时更新缓存以保证缓存数据不过期。如果我们模拟Mysql Slave的交互协议,伪装自己为Mysql Slave,向Master发送dump协议,Master收到dump请求,就会推送binary log给我们的伪Slave。接下来解析binlog,把相应的更新同步到缓存就可以了。

Python-Mysql-Replication

伪装Mysql Slave,解析binlog都需要对mysql有更深入的了解。为了把精力关注在我们的目标上,这里我选择了一个现有的python库:Python-Mysql-Replication。

官方给的demo很简单: 示例1

dump方法就会把各类event的详细信息都打印出来。我们需要关心的event类型有:DeleteRowsEvent / UpdateRowsEvent / WriteRowsEvent / RotateEvent。

前三个事件分别对应删除操作/更新操作/新增操作。看看UpdateRowsEvent包含了哪些信息:

示例2

我们需要关注的信息有date/log position/table/values。log position表示这个event在binlog文件的offset。

RotateEvent则给出当前使用的binlog的文件名(binlog文件超过指定size时会rotate,这时通过监听RotateEvent就能拿到最新的binlog文件名):

示例3

通过RotateEvent提供的binlog文件名,和DeleteRowsEvent / UpdateRowsEvent / WriteRowsEvent等Event附带的log position信息,我们就能记录当前已经处理的binlog的偏移。实际上,Mysql Slave就是通过这种方式来做增量更新的,Slave通过将Relay_Master_Log_File和Exec_Master_Log_Pos这两个字段记录在relay-log.info文件来存储同步的进度。

和udf+trigger方式的比较

使用udf+trigger的方式的优点是简单,不足主要如下:

  • 运维成本高

  • 有一定开销

  • 难以监控trigger的成功率

使用binlog的难点主要是解析比较麻烦,不过现有的各种库很好的帮我们处理了。优点主要如下:

  • 运维无成本

  • 对mysql没有什么开销

由于binlog是全库的log,如果需求是监听一两张表的数据更新,建议采用trigger+udf的方式。而如果监听的表数量较多,那么建议使用binlog的方式。