转载

MySQL主从不一致发现的细小问题分析(r12笔记第63天)

   今天和同事一起看了一个问题,她在一个主从环境中发现了数据不一致,存在主键冲突。

    show slave status的报错信息大概是下面的样子。

Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 0 failed executing transaction '0e454161-3169-11e7-98f6-02004d9d000a:665' at master log mysql-bin.000001, end_log_pos 274391. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.      这是一个MySQL 5.7版本的主从环境,还没有投入线上业务使用,是在搭建的过程中碰到了这类问题。

    一般来说,如果主从数据不一致,可以使用pt工具来尝试检查和修复。而这个问题是在搭建主从的时候出现,主从搭建貌似也没有太多的技巧,开启GTID,完全够用了,听起来确实有些奇怪。

    同事在使用pt工具修复失败之后,准备重建,但是重建的过程也很曲折,slave总是会有主键数据的冲突。我们检查了主库端,数据是没有冲突的,难道这又是bug,我觉得细细看看。

     我拿到环境,准备向从搭建从库突破,因为数据量不大,所以我重新导入了一次数据,是使用最简单的重定向方式来导入。

# mysql -pxxxxx < db-dump-201705121718.sql
Logging to file '/home/mysql/query.log'
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.  但是我运行之后发现,导入的时候报错了,在导出的时候其实可以加一个选项,这样就不会有这类干扰了。

  因为是重新搭建从库,所以我使用了reset master的方式,

> reset master;
Query OK, 0 rows affected (0.01 sec)  再次导入就没有问题了。

  接下来就是change master的设置.

CHANGE MASTER TO       MASTER_HOST='xxxx',        MASTER_USER='rep_user',        MASTER_PASSWORD='xxxx',        MASTER_PORT=3306,        MASTER_AUTO_POSITION = 1;
  启动slave后发现同事碰到的错误没有了。

  对于这个问题,我们进行了沟通,同事导入的时候使用source的方式导入,说没有看到错误,我们对比了一下搭建方法,也就这个地方不同了。

   带着试试看的态度,我使用source的方式搭建了一次。

>source db-dump-201705121718.sql   看到后台输出了很多的日志,总体来看是没有什么异常的地方。然后重启slave错误可以重现了。所以通过这个过程可以基本断定和bug无关。

  这个时候我们的关注点逐步缩小,经过论证,就是这个地方的问题,我们来通过几个小测试来说明。

  我写了几行SQL,文件a.sql包含创建表,插入两行数据的操作。

# cat a.sql
create table test(id int);
insert into test values('aaa');
insert into test values(100);使用mysql test < a.sql 还是source的方式都没有任何报错。

运行后表test的数据为:

> select *from test;
+------+
| id   |
+------+
|    0 |
|  100 |
+------+这一点确实让我有些意外。当然问题的重点不在这里,我们继续改一下脚本。

# cat a.sql
create table test(id int);
insert into test values('aaa','aa');
insert into test values(100);这个时候差别就很明显了。

# mysql test < a.sql
Logging to file '/home/mysql/query.log'
ERROR 1136 (21S01) at line 2: Column count doesn't match value count at row 1查看数据情况,是没有数据插入的。

> select *from test;
Empty set (0.00 sec) 而使用source的方式,日志如下:

> source a.sql
Query OK, 0 rows affected (0.01 sec)
ERROR 1136 (21S01): Column count doesn't match value count at row 1
Query OK, 1 row affected (0.01 sec)查看数据,是有1行数据的。

所以很大的一个差别就在于此,使用重定向的方式,如果有错误会直接退出,而使用source会依次执行,错误的地方跳过,继续执行下面的步骤。这样一个细小的地方可谓是细思恐极。对于我们做数据变更类的操作而言,是尤其重要的。




正文到此结束
Loading...