0%

MySQL主从数据一致性

在我们的系统中可能很多朋友都会遇到主从复制数据不一致的情况,有时候跑着跑着就会这样。
我整理了几个参数,是为了保证主从数据一致性。希望对大家有帮助。

  • 首先介绍一下两个文件:

|文件名 | 作用 |
|————-|:———–:|:————–:|
|relay-log-info|记录SQL线程读取Master binlog的位置,用于Slave down机之后根据文件中记录的pos点恢复SQL线程|
|master-info|记录IO线程读取已经读取到的Master binlog位置,用于Slave down机之后IO线程根据文件中记录的pos点重新拉取binlog日志|

这两个文件在写的时候并不是实时更新,而是有两个参数进行控制。

参数名 含义
sync_relay_log_info 执行多少个事务后将relay-log-info,sync一下文件刷新到磁盘上
sync_master_info 执行多少个事务后将master-info sync一下文件刷新到磁盘上

为了保证文件中内容是实时更新的(如果不是实时更新必然会造成主备主备数据不一致,例如Slave down机时,我们执行了999个事务。这时master-info还并没有sync到磁盘上,Slave恢复后就会多拉取999个事务),我们要将两个参数设置为1。
但是这里有一个问题,虽然是每一次都去sync到磁盘上,但是还是存在问题。

举个例子:

  1. 正常跑的Slave突然掉电了,但是最后一个事务已经commit成功了。但是可能还没有将sync_relay_log_info sync到磁盘上。因为sync文件这个动作并不是在事务中,不能得到保证。
  2. 等待Slave恢复之后,会去读取relay_log_info文件。就会将最后一个事务进程重做一遍,后面主备可能会正常运行但是数据会出现不一致。

MySQL中提供了两个参数:

参数名 含义
relay-log-info-repository 将relay-log-info记录到表中(slave_relay_log_info)
master-info-repository 将master-info记录到表中(slave_master_info)

当记录在表中并且sync_relay_log_info与sync_master_info设置为1的时候就不会出现上面那种情况,因为都是Innodb表有事务的保证。但是sync_master_info设置为1每一次都去刷新一次效率必然很低。
这里可能有人会有疑问sync_relay_log_info不是不需要设置为1嘛?MySQL官方文档中是这样写的:

从图中我们就明白了 relay-log-info-repository设置为记录在表中时,默认就是1.

MySQL5.6中有一个参数提供了一个参数:

  • relay_log_recovery
    这个参数的含义是,当Shalve 重启之后会根据slave_relay_log_info表重新创建一个文件,SQL线程会根据这个文件进行恢复复制,IO线程会读取SQL线程的pos点,根据这个pos点向主库申请拉取数据。

也就是我们只要设置了:
relay-log-info-repository = TABLE
relay_log_recovery = ON
就可以避免主从库数据不一致情况。