MySQL Binlog同步类似canal功能,通过MySQL slave来同步Binlog,性能较高。

功能特点

  • 通过Binlog增量采集数据库更新操作数据,性能优越。支持RDS等MySQL协议的数据库。
  • 支持多种数据库过滤方式,如正则表达式。
  • 支持Binlog位点设置。
  • 支持通过Checkpoint机制同步保存状态。

使用限制

  • 此功能目前仅支持Linux,依赖Logtail 0.16.0及以上版本,版本查看与升级请参见安装Logtail(Linux系统)
  • MySQL必须开启Binlog,且Binlog必须为row模式(默认RDS已经开启)。
    # 查看是否开启Binlog
    mysql> show variables like "log_bin";
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | log_bin       | ON    |
    +---------------+-------+
    1 row in set (0.02 sec)
    # 查看Binlog类型
    mysql> show variables like "binlog_format";
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | binlog_format | ROW   |
    +---------------+-------+
    1 row in set (0.03 sec)
  • ServerID必须唯一。确保需要同步的MySQL所有Slave的ID不重复。
  • RDS限制
    • 无法直接在RDS服务器上安装Logtail,您需要将Logtail安装在能连通RDS实例的任意一台ECS上。
    • RDS备库不支持Binlog采集,您需要配置RDS主库进行采集。

实现原理

Logtail内部实现了MySQL Slave的交互协议,具体流程如下所示。
  1. Logtail将自己伪装为MySQL的Slave节点并向MySQL的master发送dump协议。
  2. MySQL的master收到dump请求后,会将自身的Binlog实时发送给Logtail。
  3. Logtail对Binlog进行事件解析、过滤、数据解析等,并将解析好的数据上传到日志服务。
实现原理

应用场景

适用于数据量较大且性能要求较高的数据同步场景。
  • 增量订阅数据库改动进行实时查询与分析。
  • 数据库操作审计。
  • 使用日志服务对数据库更新信息进行自定义查询分析、可视化、对接下游流计算、导入MaxCompute离线计算、导入OSS长期存储等。

数据可靠性

建议您启用MySQL服务器的全局事务ID(GTID)功能,并将Logtail升级到0.16.15及以上版本以保证数据可靠性,避免因主备切换造成的数据重复采集。
  • 数据漏采集:Logtail与MySQL服务器之间的网络长时间中断时,可能会产生数据漏采集情况。

    MySQL Binlog插件通过伪装成MySQL的slave节点持续从master节点获取binlog数据。因此,Logtail会和master节点之间建立连接以获取数据。如果Logtail和master之间的网络发生中断,master节点依然会不断地产生新的binlog数据并且回收旧的binlog数据。当网络恢复且Logtail重连成功后,Logtail会使用自身的checkpoint去向master请求更多的binlog数据。而由于长时间的网络中断,它所需要的数据很可能已经被回收了,这时就会触发Logtail的异常恢复机制。在异常恢复机制中,Logtail会从master获取最近的binlog位置,以它为起点继续采集,这样就会跳过checkpoint和最近的binlog位置之间的数据,导致数据漏采集。

  • 数据重复采集:如果master和slave之间的binlog序号不同步时,发生了主备切换事件,可能会产生数据重复采集情况。

    在MySQL主备同步的设置下,master会将产生的binlog同步给slave,slave收到后会存储到本地的binlog文件中。如果master和slave之间的binlog序号不同步时,发生了主备切换事件,以binlog文件名和偏移作为checkpoint的机制将导致数据重复采集。

    例如,有一段数据在master上位于(binlog.100, 4)(binlog.105, 4)之间,而在slave上是(binlog.1000, 4)(binlog.1005, 4),并且Logtail已经从master获取了这部分数据,将本地checkpoint更新到了(binlog.105, 4)。如果此时发生了主备切换且无任何异常发生,Logtail将会继续使用本地checkpoint(binlog.105, 4)去向新master获取binlog信息。但是因为新master上的(binlog.1000, 4)(binlog.1005, 4)这部分数据的序号都大于Logtail所请求的序号,它会把它们返回给Logtail,这就引起了binlog数据的重复采集。

配置项

MySQL Binlog方式输入源类型为:service_canal
配置项 类型 是否必须 说明
Host string 数据库主机,默认为127.0.0.1。
Port int 数据库端口,默认为3306。
User string 数据库用户名,默认为root。
需保证配置的用户具有数据库读权限以及MySQL REPLICATION权限,示例如下。
CREATE USER canal IDENTIFIED BY 'canal';  
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;
Password string 数据库密码,默认为空。
如果安全需求较高,建议将SQL访问用户名和密码配置为xxx,待配置同步至本地机器后,在/usr/local/ilogtail/user_log_config.json文件找到对应配置进行修改。
说明
  • 修改完毕后请执行sudo /etc/init.d/ilogtaild stop; sudo /etc/init.d/ilogtaild start命令重启Logtail。
  • 如果您在Web端修改了此配置,配置同步至本地后会覆盖当前本地的配置,请根据需要手动修改本地配置。
ServerID int Logtail伪装成的Mysql Slave ID,默认为125。
说明 ServerID对于MySQL数据库必须唯一,否则会同步失败。
IncludeTables string 数组 包含的表名称(包括db,例如test_db.test_table),为正则表达式。若某个表不符合IncludeTables的任一条件则该表不会被采集。如果您希望采集所有表,请将此参数指定为.*\\..*
说明 若需要完全匹配,请在前后分别加上^$,例如^test_db\\.test_table$
ExcludeTables string 数组 忽略的表名称(包括db,例如test_db.test_table),为正则表达式。若某个表符合ExcludeTables的任一条件则该表不会被采集。不设置时默认收集所有表。
说明 若需要完全匹配,请在前后分别加上^$,例如^test_db\\.test_table$
StartBinName string 首次采集的Binlog文件名,不设置时默认从当前时间点开始采集。
如果想从指定位置采集,可以查看当前的Binlog以及offset,并将StartBinNameStartBinLogPos设置成对应的值,示例如下。
# StartBinName 设置成 "mysql-bin.000063", StartBinLogPos 设置成 0
mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000063 |       241 |
| mysql-bin.000064 |       241 |
| mysql-bin.000065 |       241 |
| mysql-bin.000066 |     10778 |
+------------------+-----------+
4 rows in set (0.02 sec)
说明

当指定StartBinName时,第一次采集会产生较大流量。

StartBinLogPos int 首次采集的Binlog文件名的offset,默认为0。
EnableGTID bool 是否附加全局事务ID。默认为true,为false时上传的数据将不附加全局事务ID。
EnableInsert bool 是否收集insert事件的数据。默认为true,为false时将不采集insert事件数据。
EnableUpdate bool 是否收集update事件的数据。默认为true,为false时将不采集update事件数据。
EnableDelete bool 是否收集delete事件的数据。默认为true,为false时将不采集delete事件数据。
EnableDDL bool 是否收集DDL(data definition language)事件数据。 默认为false表示不收集DDL事件数据。
说明 该选项不支持IncludeTablesExcludeTables过滤。
Charset string 编码方式,默认为utf-8
TextToString bool 是否将text类型数据转换成string,默认为false。
PackValues bool 是否将事件的数据打包成JSON格式。默认为false表示不打包。如果开启此功能,Logtail会将事件数据以JSON格式集中打包到data和old_data两个字段中,其中old_data仅在row_update事件中有意义。

示例:假设数据表有三列数据c1,c2,c3,在不开启此功能的情况下,row_insert事件数据中会有c1,c2,c3三个字段,而开启此功能后,c1,c2,c3会被统一打包为data字段,值为{"c1":"...", "c2": "...", "c3": "..."}

说明 该参数仅支持Logtail 0.16.19及以上版本。
EnableEventMeta bool 是否采集事件的元数据,默认为false表示不采集。 Binlog事件的元数据包括event_timeevent_log_positionevent_size以及event_server_id
说明 该参数仅支持Logtail 0.16.21及以上版本。

操作步骤

从RDS中同步user_info库中不以_inner结尾的表,配置如下。

  1. 登录日志服务控制台,单击Project名称。
  2. 选择输入源。
    单击接入数据按钮,并在接入数据页面中选择MYSQL BINLOG
  3. 选择日志空间。
    请选择Project和Logstore,您也可以直接单击立即创建新建Project和Logstore。具体步骤请参见准备流程

    如果您是通过日志库下的数据接入后的加号进入采集配置流程,系统会直接跳过该步骤。

  4. 创建机器组。
    在创建机器组之前,您需要首先确认已经安装了Logtail。 安装完Logtail后单击确认安装完毕创建机器组,具体请参见简介。如果您之前已经创建好机器组 ,也可以直接单击使用现有机器组
  5. 配置机器组。
    选择一个机器组,将该机器组从源机器组移动到应用机器组机器组配置
  6. 设置数据源。
    填写配置名称和插件配置。
    插件配置输入框中已为您提供配置模板,请根据您的需求替换配置参数。
    {
     "inputs": [
         {
             "type": "service_canal",
             "detail": {
                 "Host": "************.mysql.rds.aliyuncs.com",
                 "Port": 3306,
                 "User" : "root",
                 "ServerID" : 56321,
                 "Password": "*******",
                 "IncludeTables": [
                     "user_info\\..*"
                 ],
                 "ExcludeTables": [
                     ".*\\.\\S+_inner"
                 ],
                 "TextToString" : true,
                 "EnableDDL" : true
             }
         }
     ]
    }
    • inputs部分为采集配置,必选项。请根据您的数据源配置对应的采集语句。
    • processors部分为处理配置,可选项。请参见处理采集数据配置一种或多种采集方式。
  7. 设置索引。
    查询分析配置阶段设置索引,默认已经设置好索引,您也可以根据业务需求,重新设置索引。具体请参见开启并配置索引
  8. 可选: 修改本地配置。
    如果您没有在插件配置中输入真实的URL、账号、密码等信息,需要在采集配置下发到本地后手动修改其中的内容。
    说明 如果您服务端输入的是真实信息,则无需此步骤。
    1. 登录Logtail所在服务器,查找/usr/local/ilogtail/user_log_config.json文件中service_canal关键词,修改下述对应的HostUserPassword等字段。
    2. 执行以下命令重启Logtail。
      sudo /etc/init.d/ilogtaild stop; sudo /etc/init.d/ilogtaild start
Binlog采集配置已经完成,如果您的数据库存在对应的修改操作,则Logtail会立即将变化的数据采集到日志服务。
说明 Logtail默认采集Binlog的增量数据,如查看不到数据请确认在配置更新后数据库的表存在修改操作。

元数据字段

Binlog采集会将一些元数据和日志一起上传,具体上传的元数据列表如下。
字段 说明 示例
_host_ 数据库host名称。 *********.mysql.rds.aliyuncs.com
_db_ 数据库名称。 my-database
_table_ 表的名称。 my-table
_event_ 事件类型。 row_updaterow_insertrow_delete
_id_ 本次采集的自增ID,从0开始,每次采集一个binlog事件后加1。 1
_gtid_ GTID。 7d2ea78d-b631-11e7-8afb-00163e0eef52:536
_filename_ Binlog文件名。 binlog.001
_offset_ Binlog文件偏移量,该值只会在每次commit后更新。 12876

示例

按照以上操作步骤配置处理方式后,对user_info 下的SpecialAlarm表分别执行INSERTUPDATEDELETE操作。数据库表结构、数据库操作及Logtail采集的样例如下。
  • 表结构
    CREATE TABLE `SpecialAlarm` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    `time` datetime NOT NULL,
    `alarmtype` varchar(64) NOT NULL,
    `ip` varchar(16) NOT NULL,
    `count` int(11) unsigned NOT NULL,
    PRIMARY KEY (`id`),
    KEY `time` (`time`) USING BTREE,
    KEY `alarmtype` (`alarmtype`) USING BTREE
    ) ENGINE=MyISAM AUTO_INCREMENT=1;
  • 数据库操作
    执行INSERT、DELETE和UPDATE三种操作。
    insert into specialalarm (`time`, `alarmType`, `ip`, `count`) values(now(), "NO_ALARM", "10.10.**.***", 55);
    delete from specialalarm where id = 4829235  ;
    update specialalarm set ip = "10.11.***.**" where id = "4829234";
    zc.specialalarm创建一个索引。
    ALTER TABLE `zc`.`specialalarm` 
    ADD INDEX `time_index` (`time` ASC);
  • 样例日志
    在数据预览或查询分析页面中,可以看到对应每种操作的样例日志如下。
    • INSERT语句
      __source__:  10.30.**.**  
      __tag__:__hostname__:  iZbp145dd9fccu*****  
      __topic__:    
      _db_:  zc  
      _event_:  row_insert  
      _gtid_:  7d2ea78d-b631-11e7-8afb-00163e0eef52:536  
      _host_:  *********.mysql.rds.aliyuncs.com  
      _id_:  113  
      _table_:  specialalarm  
      alarmtype:  NO_ALARM  
      count:  55  
      id:  4829235  
      ip:  10.10.***.***  
      time:  2017-11-01 12:31:41
    • DELETE语句
      __source__:  10.30.**.**  
      __tag__:__hostname__:  iZbp145dd9fccu****
      __topic__:    
      _db_:  zc  
      _event_:  row_delete  
      _gtid_:  7d2ea78d-b631-11e7-8afb-00163e0eef52:537  
      _host_:  *********.mysql.rds.aliyuncs.com  
      _id_:  114  
      _table_:  specialalarm  
      alarmtype:  NO_ALARM  
      count:  55  
      id:  4829235  
      ip:  10.10.**.***
      time:  2017-11-01 12:31:41
    • UPDATE语句
      __source__:  10.30.**.**  
      __tag__:__hostname__:  iZbp145dd9fccu****  
      __topic__:    
      _db_:  zc  
      _event_:  row_update  
      _gtid_:  7d2ea78d-b631-11e7-8afb-00163e0eef52:538  
      _host_:  *********.mysql.rds.aliyuncs.com  
      _id_:  115  
      _old_alarmtype:  NO_ALARM  
      _old_count:  55  
      _old_id:  4829234  
      _old_ip:  10.10.22.133  
      _old_time:  2017-10-31 12:04:54  
      _table_:  specialalarm  
      alarmtype:  NO_ALARM  
      count:  55  
      id:  4829234  
      ip:  10.11.***.***
      time:  2017-10-31 12:04:54
    • DDL(data definition language)语句
      __source__:  10.30.**.**  
      __tag__:__hostname__:  iZbp145dd9fccu****  
      __topic__:    
      _db_:  zc  
      _event_:  row_update  
      _gtid_:  7d2ea78d-b631-11e7-8afb-00163e0eef52:539  
      _host_:  *********.mysql.rds.aliyuncs.com  
      ErrorCode:  0
      ExecutionTime:  0
      Query:  ALTER TABLE `zc`.`specialalarm` 
      ADD INDEX `time_index` (`time` ASC)
      StatusVars:

注意事项

建议您适当放开对Logtail的资源限制以应对流量突增,避免Logtail因为资源超限被强制重启,对您的数据造成不必要的风险。

资源限制可通过修改/usr/local/ilogtail/ilogtail_config.json文件实现,修改完成后执行命令sudo /etc/init.d/ilogtaild stop;sudo /etc/init.d/ilogtaild start重启Logtail。

如下示例表示将CPU的资源限制放宽到双核,将内存资源的限制放宽到2048MB。
{
    ...
    "cpu_usage_limit":2,
    "mem_usage_limit":2048,

    ...
}