

01
环境概况 & 初步排查.
问题环境概况及部分参数
MySQL Version:5.7.27同步方式:ROW+GTID+增强半同步关键参数:rpl_semi_sync_master_wait_point=AFTER_SYNCslave_parallel_type=LOGICAL_CLOCKslave_parallel_workers=8binlog_transaction_dependency_tracking=COMMIT_ORDER
初步排查
查看主从同步状态:
show slave status\G;

现象:通过结果可以看出Slave_IO_Running、Slave_SQL_Running状态都为Yes,证明IO_Thread和SQL_Thread是正常的,但是Seconds_Behind_Master却在一直增长,很奇怪,所以首先想到的是大事务导致的。
主库,查看所有进程:
show processlist;

看起来没有什么问题,正常连接到数据库的操作用户也都为Sleep,主库上没有执行大事务。
从库,查看所有进程:

02
延迟原因定位.
通过上面的初步判断得到的结论是从库处于Executing event状态,SQL_Thread正在且只有一个worker线程在工作,并行复制模式已退化成单线程模式了。所以,再次看一下主从同步状态:
show slave status\G;
多次执行后发现:

/usr/local/mysql3307/bin/mysqlbinlog -v --base64-output=decode-rows --start-position=996411549 /mysql/mysql3307/mysql-bin.000006 > mysqlbinlog.log


SHOW CREATE TABLE `demo`.`ke_consumer`;SELECT COUNT(*) FROM `demo`.`ke_consumer`;

03
问题处理 & 原理浅析.
问题处理

stop slave;
3、确定出条件选择性好的字段:timespan
SELECT * FROM `demo`.`ke_consumer` limit 10;SELECT COUNT(DISTINCT(timespan)),COUNT(*) FROM `demo`.`ke_consumer`;

SET sql_log_bin=0;ALTER TABLE `demo`.`ke_consumer` ADD UNIQUE INDEX(timespan);
SET sql_log_bin=1;start slave;
6、多次检查同步状态:
show slave status\G;
7、确认Exec_Master_Log_Pos是否还会发生不变的情况。如发生同样使用解析binlog文件和position的方式定位并重复上述步骤。并最终确定同步状态完全正常。
# 解析binlog日志确定大事务所在语句/usr/local/mysql3307/bin/mysqlbinlog -v --base64-output=decode-rows --start-position=33077322 /mysql/mysql3307/mysql-bin.000007 > mysqlbinlog_1.log/usr/local/mysql3307/bin/mysqlbinlog -v --base64-output=decode-rows --start-position=140003442 /mysql/mysql3307/mysql-bin.000007 > mysqlbinlog_2.logmore mysqlbinlog_1.logmore mysqlbinlog_2.log# 停止同步stop slave;# 设置执行SQL不记录binlogset sql_log_bin=0;# 条件选择性好的字段添加唯一索引ALTER TABLE `demo`.`ke_logsize` ADD UNIQUE INDEX(timespan);ALTER TABLE `demo`.`ke_consumer_bscreen` ADD UNIQUE INDEX(timespan);# 还原执行SQL记录binlogset sql_log_bin=1;# 启动同步start slave;# 确认同步状态show slave status\G;

Q-3:创建索引后,会影响同步吗?
原理浅析
为什么没有主键的表在同步的时候会产生延迟呢?因为MySQL主从复制是基于行的复制,假设主库执行一个'DELETE FROM T;'的SQL(表T中有10000行记录),这时MySQL会把这个SQL按照每条记录,拆分成10000条DELETE SQL(刚才我们解析出的binlog文件截图也已经验证)在备库上执行,MySQL这么做的目的也是最大程度的保证同步数据的可靠性。
但是可靠性的提升伴随而来的便是日志量的增多,同步过程会占用大量带宽。
其次,表即无主键,也没有索引。所以在从库回放过程中每执行一次DELETE SQL都要做全表扫描才能定位到要删除的那一条数据。如果数据量很大,每次执行一条SQL,全表扫描一次,操作成本和时长可想而知。同时没有主键,并行复制也可能会退化为单线程模式,就好比100件事情1人做和100件事情好多人做一样。
04
小结.
,写作素材又有了,有时间我会把我收集的数据库开发规范整理一下出一篇文章,等我!~
end




