目录

阿里云采坑记录 | RDS 的 binglog 丢失

本文介绍阿里云数据库 binglog 配置注意点.

一、前言

上周同事负责的同步服务出现宕机后,由于在忙于另一个重要的项目,线上没有及时处理,后发现同步数据丢失.我趁机了解了下我们的同步逻辑并对这次异常做一个简单的总结.

情况描述:

线上我们基于 otter 的 msyql 数据同步服务出错,出错后会停止数据同步(我们后续的配置没有从中心节点同步到私有云节点),导致了私有云无法正常启动部分服务.

  • 我们分阿里云(中心节点),北京私有云节点,广州私有云节点等,数据会从中心节点同步到私有云节点
  • 中心节点使用了阿里云的RDS MySQL数据库,私有云节点采用自己搭建的MySQL
  • 采用基于otter的数据同步服务(otter基于canal)
  • 我们采用了xxl-job来做定时调度,因为之前认为它只有DML操作,我们的同步服务没有对它的DDL操作做处理
  • xxl-job的机器配置的较低,数据量变大之后XXL_JOB_QRTZ_TRIGGER_LOG的查询语句运行较慢,我们给它增加了个索引
  • 我们的同步服务异常后,会停止数据同步
  • A服务发布,在中心节点加了配置,私有云节点启动失败
  • 查询发现同步服务异常,无法通过binlog的偏移量找到记录,导致无法把中心节点加了的配置同步到私有云节点
  • 我们是在一天后对这个问题做的处理

二、排查

2.1 xxl job的变化

xxl-job的SQL:

 1SELECT t.id, t.job_group, t.job_id, t.executor_address, t.executor_handler
 2  , t.executor_param, t.executor_sharding_param, t.executor_fail_retry_count, t.trigger_time, t.trigger_code
 3  , t.trigger_msg, t.handle_time, t.handle_code, t.handle_msg
 4FROM XXL_JOB_QRTZ_TRIGGER_LOG t
 5WHERE t.job_group = ?
 6  AND t.job_id = ?
 7  AND t.trigger_time >= ?
 8  AND t.trigger_time <= ?
 9ORDER BY id DESC
10LIMIT ?, ?

并没有异常情况.

2.2 MySQL 排查

mysql 查看 binlog:

 1// 查看binlog文件列表
 2mysql> show binary logs;
 3+------------------+-----------+
 4| Log_name         | File_size |
 5+------------------+-----------+
 6| mysql-bin.000001 |    107853 |
 7+------------------+-----------+
 81 row in set (0.00 sec)
 9
10
11// 查看binlog状态
12mysql> show master status;
13+------------------+----------+--------------+------------------+-------------------+
14| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
15+------------------+----------+--------------+------------------+-------------------+
16| mysql-bin.000001 |   107853 |              |                  |                   |
17+------------------+----------+--------------+------------------+-------------------+
181 row in set (0.00 sec)

并没有异常情况.

三、解决方案

因为同步服务是由于binlog的偏移量问题而失败,偏移量是通过zk节点去获取的,我们去MySQL查询了最新的可用的偏移量,设置到了zk的指定节点,让同步服务正常运行.(我们的配置同步在新偏移量之后,所以启动后能够从中心节点同步到私有云节点)

这个是临时的解决方案,我们没法找到之前的binlog的完整记录

四、思考问题

4.1 为什么过了一天,同步服务会启动失败?

同步服务失败,因为binlog找不到.MySQL我们自己安装的话binlog配置默认是不清理的,但是RDS上不是这样的. 下面是RDS默认配置:

  • 保留时长:默认值为18,表示实例空间内默认保存最近18个小时内的Binlog文件,18个小时之前的日志将在备份后(需要开启日志备份)清理.保留时长可选范围值为0~7*24小时.
  • 空间使用率不超过:默认值为30%,表示本地Binlog空间使用率大于30%时,系统会从最早的Binlog开始清理,直到空间使用率低于30%.空间使用率不超过可选范围值为0 - 50% .
  • 可用空间保护,默认开启该功能,表示当实例总空间使用率超过80%或实例剩余可用空间不足5GB时,会强制从最早的Binlog开始清理,直到总空间使用率降到80%以下且实例剩余可用空间大于5GB.

我们可以看到RDS默认保留时间小于一天,所以我们停了一天后再度开启,导致binlog位置找不到,只能从最新的偏移量同步.这里首先把保留时长调至3天(我们的同步服务不可能停3天,在某些改造项目,同步服务可能会停1-2天),这个需要根据实际场景去设置合理的值.

4.2 binlog不在了,如何补救?

阿里云会把binlog保存到OSS,从OSS下载回来binlog,然后把binlog设置到MySQL指定位置(这块可能是我脑补的).这块有任何问题可以提工单,毕竟顾客是“上帝”.

本地验证的时候,位置是:

1/usr/local/mysql/data