mysql主从同步表结构不一致

时间:2024-03-14 10:25:42

最近在工作中遇到一个非常奇怪的问题,在两台主主同步的mysql数据库中,经常出现修改表结构后,两个库中结构不一致的情况,查看同步状态,木有任何报错,数据可正常同步,我自己在操作数据库进行索引创建也可同步。接下来就开始了各种找根源,脑细胞极速死亡~


第一步:初探binlog

binlog文件以Row模型进行存储的(还可设置为Statement或Mixed),具体每种类型的区别网上很多(Binlog日志模型),拉取binlog日志需要用到mysqlbinlog,网上一番查找,终于找到了参数详情(mysqlbinlog命令参数详解),这下终于可以看日志了

                     # at 315449838
                     #181016 16:03:13 server id 2  end_log_pos 315450001 CRC32 0xb99978af     Query    thread_id=12181                                              exec_time=0    error_code=0
                     SET TIMESTAMP=1539676993/*!*/;
                     SET @@session.sql_mode=0/*!*/;
                     SET @@session.auto_increment_increment=2, @@session.auto_increment_offset=2/*!*/;
                     alter TABLE XXXXdatabase.xxxTable ADD COLUMN resever2 INT

看完日志,一脸懵逼,可以说语句写得相当正常

mysql主从同步表结构不一致

 

抱着万物皆有因的人生真谛,我开始了下一步的思考:


第二步:挖掘relay-log

在mysql同步中,主服务器通过binlog日志记录操作事件,从服务器通过IO线程读取binlog日志,生成relay-log日志,再由从服务器读取relaylog执行操作。所以,博主开心的开始了查看relay-log日志过程,以下就是我查看完之后的表情

mysql主从同步表结构不一致

 

relaylog中将binlog中的所有日志都正常拉取到了,心中简直就是十万个为什么,为什么拉取到了“没有执行”?如果执行了,为什么执行效果和主备不一致?找Row模式的参数详情,无解;找事件同步等级,无解。。。到此时,已经过去了大半天,罢了罢了,惹不起,不如回家做饭吃!!!果断下班。。。


第三步:直击人性

在下一个秋(bu)风(xiang)和(shang)煦(ban)的早上,不死心的我又开始了一番对比捣鼓,突然间,看到了前一天创建索引的binlog日志信息(用create创建的,所以一直以为是alter语句无法同步),脑海中神经突然碰撞连接,将create和alter的两个事件日志进行了360度无死角比对。

                     # at 315111302
                     #181016 14:50:56 server id 2  end_log_pos 315111456 CRC32 0x12c03d24     Query    thread_id=12165                                              exec_time=3    error_code=0
                     use `XXXXdatabase`/*!*/;
                     SET TIMESTAMP=1539672656/*!*/;
                     SET @@session.sql_mode=0/*!*/;
                     SET @@session.auto_increment_increment=2, @@session.auto_increment_offset=2/*!*/;
                     CREATE INDEX log_user_id_key ON xxxTable(user_id)

看到木有,这个比alter多了一个进库的步骤,此刻心中已有了一个大胆的猜想,是不是alter时的语句格式有问题,在主从同步情况下,不支持直接在语句中引用数据库?talk is cheap,show you code!,进入主服务器,再进入数据库,再执行

alter xxxTable ADD COLUMN resever2 INT

此刻,同步了。。了。。。了。。。。

再次拉取出binlog日志如下:

                     # at 318394813
                     #181017 11:20:43 server id 2  end_log_pos 318394975 CRC32 0xecb8e18c     Query    thread_id=12316                                              exec_time=0    error_code=0
                     use `XXXXdatabase`/*!*/;
                     SET TIMESTAMP=1539746443/*!*/;
                     SET @@session.sql_mode=0/*!*/;
                     SET @@session.auto_increment_increment=2, @@session.auto_increment_offset=2/*!*/;
                     alter xxxTable ADD COLUMN resever2 INT

至此,真相大白,线上的多次不同步竟是因为在执行sql语句时想要一步搞定偷懒所致。。。。可以说是很骨感很现实了。至于为什么直接引用数据库时无法正确执行,以后慢慢再去研究~