percona server 8.0主从同步延迟分析
一、背景
最近在归档几亿业务数据到我们自建的MySQL集群,发现数据库主从同步延迟很大,MySQL版本为percona server 8.0.19,存储引擎为TokuDB,机器为腾讯云CVM,配置为2c 4G,磁盘为1T高性能云盘。
二、原因分析
1、第一时间登录服务器发现,IO wait很高,第一反应就是磁盘IO不足导致的。
2、登录MySQL发现,secondary和primary相差了四百多个binlog,IO thread拉取binlog很慢,slave thread重放完了relay log,一直在等待新的relay log,所以调整了sync_binlog = 0,但是发现情况并没有任何改善。
3、用perf分析MySQL进程是哪个函数占用cpu较高,当然DBA也可以使用strace去分析堆栈信息,只是会比较耗时,如图所示
从上面我们可以知道问题大概率出现在flush_master_info这个函数,所以我们去搜索percona server的源码,源码位置为percona-server-8.0.19-10/sql/rpl_slave.cc,代码片段如下
int flush_master_info(Master_info *mi, bool force, bool need_lock,
bool do_flush_relay_log) {
DBUG_TRACE;
DBUG_ASSERT(mi != nullptr && mi->rli != nullptr);
DBUG_EXECUTE_IF("fail_to_flush_master_info", { return 1; });
/*
With the appropriate recovery process, we will not need to flush
the content of the current log.
For now, we flush the relay log BEFORE the master.info file, because
if we crash, we will get a duplicate event in the relay log at restart.
If we change the order, there might be missing events.
If we don't do this and the slave server dies when the relay log has
some parts (its last kilobytes) in memory only, with, say, from master's
position 100 to 150 in memory only (not on disk), and with position 150
in master.info, there will be missing information. When the slave restarts,
the I/O thread will fetch binlogs from 150, so in the relay log we will
have "[0, 100] U [150, infinity[" and nobody will notice it, so the SQL
thread will jump from 100 to 150, and replication will silently break.
*/
mysql_mutex_t *log_lock = mi->rli->relay_log.get_log_lock();
mysql_mutex_t *data_lock = &mi->data_lock;
if (need_lock) {
mysql_mutex_lock(log_lock);
mysql_mutex_lock(data_lock);
} else {
mysql_mutex_assert_owner(log_lock);
mysql_mutex_assert_owner(&mi->data_lock);
}
int err = 0;
/*
We can skip flushing the relay log when this function is called from
queue_event(), as after_write_to_relay_log() will already flush it.
*/
if (do_flush_relay_log) err |= mi->rli->flush_current_log();
err |= mi->flush_info(force);
if (need_lock) {
mysql_mutex_unlock(data_lock);
mysql_mutex_unlock(log_lock);
}
return err;
}
从代码和注解上,我们可以知道主要跟flush mater info和relay log操作有关,消耗过多IO。
4、调整MySQL参数如下
set global sync_master_info=10000;
set global sync_relay_log=10000;
set global sync_relay_log_info=10000;
之前上面那三个参数为了安全,在配置文件设置的是1,MySQL 8.0默认参数是10000,修改完毕后重启同步线程stop/start slave,发现IO thread拉取binlog正常了
不过同步延迟还是很大,毕竟拖了挺长时间了,show full processlist查看进程信息是没办法使用并行复制的,毕竟归档库没什么并发,就一个归档程序再串行跑,没用好group commit的优势。
为了加快后续新数据重放速度,开启writeset复制,不过对于目前的relay log延迟就慢慢地先让sql thread慢慢重放了。
三、总结
之前由于是用于归档的库,对于机器配置要求不高,没有使用SSD云盘,所以突然归档大量数据后,磁盘IO有点吃不消了,上面参数调整主要减轻IO消耗,因为每次都需要调用fdatasync写磁盘,代价还是挺高的。
扫描二维码获取
更多精彩
DBA入坑指南
点个在看 你最好看