在上班后的第一个星期,老大让我去搞数据库的主从同步,主要是一台在肇庆机房的服务器,首先先说一下公司的数据库架构,主要是多主一从,而我需要操作的这台从库是mariadb-10.0.13版本,从mariadb-10.0版本以后,就可以同时作为多个主库的从库了。而我同步的主库是mysql5.1版本,按照常规的做法,步骤如下:
1、除了主库在备份的时候指定所需要备份的库,我还加了--lock-all-tables和--flush-logs参数,这样可以快速锁定masterinfo的binlog文件名和pos点
2、备份完后,将备份的数据传到从库,然后导进从库
3、根据刷新的binlog和pos点修改masterinfo的信息
4、开启主从同步的开关(由于是多主一从,所以在从库的配置参数里面对不同主库的数据库进行了别名的设置),如start slave ‘bbs’;
以上一切的步骤都非常顺利,然后show slave ‘bbs’ status\G查看主从同步的状态,如图:
貌似是没有任何问题的,但是打开监控页面(这个是php的一个程序,用于主库和从库数据的比对),某些库的表的数据有差异,如图:
数据相差几十条甚至上百条,这个是很正常的,因为在从库导入数据的时候,主库会不断有数据更新的,但是只要开启主从同步之后,从库就会慢慢的同步上来
(半个小时以后……)
再次查看监控页面,却惊讶的发现主从之间数据的差异在不断的扩大(即主库不断有数据更新,但从库对应的这三个表的数据由始至终都没有更新),这下头大了,是怎么回事,以前并没有遇过这种情况。
在解决这个问题之前,我有做过一些操作,那些操作结果都是失败的,不过这里也分享一下:
①我将主库与从库之间差异的数据导出来,然后导进从库,主要的参数有--replace, 主要的作用是使用REPLACE INTO 取代INSERT INTO,再对齐好数据之后,然后过一会再次查看,差异又变大了,以失败告终。这种方法很耗时间和精力,因为要找主从表之间的差异部分,如果选择这个表导出来,小表还好说,大表就很耗时间了。
②在得到老大的同意后,在凌晨的时候进行了一小段时间的停库,在确保主从数据都对齐的情况下,开启了主库和主从同步,刚开始看还是没什么问题的,但是过了一会之后又出现了之前的情况,郁闷!!
最后老大让我逐步来排除,在排查过程中果然发现端倪了,具体的步骤是:
1、在SQL线程和IO线程都正常的情况下,先看看从库的pos点是否时刻在变化,如果pos点有变化的情况下,说明IO线程工作是正常的
2、接着就是用tail -f 查看relay-log的更新状况,能够时刻看到SQL语句的更新,并且还发现cdb_members表有数据的更新,如图:
通过排查,基本上可以确定这些SQL语句并没有写到数据库内。但是为什么没有写到数据库里面呢,在咨询老大之后,老大和我说可能存在跨库更新的情况。在上网搜索了一番之后,终于对跨库更新有了一定的概念。
首先要说明一下里面涉及的关键参数,replicate_do_db和replicate_wild_do_table,当从库只需要同步主库的某个库(表)或某几个库(表)的时候,就可以用到这两个参数,又或者用replicate_ignore_db和replicate_wild_ignore_table来忽略那些不需要更新的库和表,现在主要来说一下replicate_do_db和replicate_wild_do_table这两个参数的区别:
举个例子来说:
某两个数据库已经实现了主从同步,现在主库中有两个数据库test01和test02,然后test01中有一张表table01,如果在my.cnf的参数里面设置了replicate_do_db=test01,test02,即只同步这两个库的数据,然后执行以下的更新语句
use test01;
update test01.table1 set……
执行的结果是主从库都能看到更新的数据
但如果是另外一种执行的情况进行更新语句
use test02;
update test01.table1 set……
执行的结果是主库能够看到数据,但是从库却无法看到更新的数据
原因:设置replicate_do_db后,MySQL执行sql前检查的是当前默认数据库,所以跨库更新语句在Slave上会被忽略。
而对于跨库更新SQL语句的问题,replicate_wild_do_table可以解决,即在my.cnf的参数里面设置
(正确写法)
replicate_wild_do_table=test01.%
replicate_wild_do_table=test02.%
(错误写法)
replicate_wild_do_table=test01.%,test02.%
注意需要同步的库必须分行写而不能在同一行用逗号隔开,否则在同步的时候该参数不生效
下面是mysql官方文档的一段说明
Warning
To specify multiple databases you must use multiple instances of this option. Because database names can contain commas, if you supply a comma separated list then the list
will be treated as the name of a single database.