最近在工作中遇到一个非常奇怪的问题,在两台主主同步的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
看完日志,一脸懵逼,可以说语句写得相当正常
抱着万物皆有因的人生真谛,我开始了下一步的思考:
第二步:挖掘relay-log
在mysql同步中,主服务器通过binlog日志记录操作事件,从服务器通过IO线程读取binlog日志,生成relay-log日志,再由从服务器读取relaylog执行操作。所以,博主开心的开始了查看relay-log日志过程,以下就是我查看完之后的表情
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语句时想要一步搞定偷懒所致。。。。可以说是很骨感很现实了。至于为什么直接引用数据库时无法正确执行,以后慢慢再去研究~