MySQL8.0真正的并行复制writeset
迪丽瓦拉
2024-05-31 11:07:20
0

MySQL 主从复制模型

在这里插入图片描述
MySQL的主从架构依赖于 MySQL Binlog 功能, Master节点上产生Binlog并将Binlog写入到Binlog文件中。Slave节点上启动两个线程:一个IO线程,从MySQL上捞取Binlog日志并写入到本地的RelayLog日志;另一个SQL线程,不断的从RelayLog日志中读取日志,并解析执行。这样通过在主机和从机上增加几个文件的顺序读写操作,就可以保证所有在主机上执行过的SQL语句都在从机上一摸一样的执行过一遍。而复制延迟,指的就是一个事务在Master执行完成以后,要多久以后才能在Slave上执行完成。

由于对Binlog文件以及RelayLog文件的读写均为顺序操作,在生产环境中,Slave上的IO线程对Binlog文件的Dump操作是很少产生延迟的。 实际上,从MySQL 5.5 开始,MySQL官方提供了半同步复制插件,每个事务的Binlog需要保证传输到Slave写入 RelayLog 后才能提交,这种架构在主从之间提供了数据完整性,保证了主机在发生故障后从机可以拥有完整的数据副本。因此,复制延迟通常发生在SQL线程执行的过程中。从架构图上可以看到,最早的主从复制模型中,只有一个线程负责执行 Relaylog,也就是说所有在主机上的操作,在从机上是串行回放的。 这就带来一个问题,如果主上写入压力比较大,那么从上的回放速度很有可能会一直跟不上主。(除此之外,MySQL的架构决定了Binlog只有在Commit阶段才会写入Binlog文件并Dump给从机,这也导致主从事务必然有执行延迟,这个问题在大事务中体现的特别明显,不过这个问题就不在本文的讨论范围内了)

既然主从延迟的问题是单线程回放RelayLog太慢,那么减少主从延迟的方案自然就是提高从机上回放RelayLog 的并行度。

并行复制的演进

MySQL5.6中的并行复制————Schema级别的并行复制
MySQL5.7中的并行复制————基于Group Commit 的并行复制
MySQL8.0 中的并行复制———真正的并行复制writeset

8.0开启writeset方式

主库

mysql> show variables like '%transaction_write_set_extraction%';
+----------------------------------+----------+
| Variable_name                    | Value    |
+----------------------------------+----------+
| transaction_write_set_extraction | XXHASH64 |
+----------------------------------+----------+mysql> set global binlog_transaction_dependency_tracking = 'WRITESET';
Query OK, 0 rows affected (0.00 sec)

从库

stop slave sql_thread;
set global slave_parallel_type='logical_clock';
set global slave_parallel_workers=4;
start slave sql_thread;

不设置的情况下从库状态

从库在不设置slave_parallel_type和slave_parallel_workers的情况下,也就是说默认值database和0时,主库施加压力时,主从延迟是明显的

        Seconds_Behind_Master: 765
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 802Master_UUID: 508dae34-936b-11ea-97c0-fec9c355c78fMaster_Info_File: mysql.slave_master_infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Applying batch of row changes (write)Master_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: 

SQL Thread和IO Thread相差2个relay log,在开启从库参数后,主从延迟降低明显,show processlist可以看到4个协同线程在疯狂的加班。Applying batch of row changes 批量的写入,batch表示批量!!

mysql> show processlist;
+----+-----------------+-----------------+------+------------------+---------+---------------------------------------------------------------+------------------+
| 61 | system user     |                 | NULL | Query            |       1 | Waiting for slave workers to process their queues             | NULL             |
| 62 | system user     |                 | mc   | Query            |     507 | Applying batch of row changes (write)                         | NULL             |
| 63 | system user     |                 | mc   | Query            |     517 | Applying batch of row changes (write)                         | NULL             |
| 64 | system user     |                 | mc   | Query            |     508 | Applying batch of row changes (write)                         | NULL             |
| 65 | system user     |                 | mc   | Query            |     519 | Applying batch of row changes (write)                         | NULL             |
+----+-----------------+-----------------+------+------------------+---------+---------------------------------------------------------------+------------------+

可以看到非常容易就在一组内,这就是并行复制效率提升的原因了,很多事务都在一组之内,可以组提交

mysqlbinlog mysql-bin.000026  | grep last_committed | awk '{print $1 , $2 , $10 , $11, $12}'
#210824 14:41:10 GTID last_committed=0 sequence_number=1
#210824 14:41:11 GTID last_committed=0 sequence_number=2
#210824 14:41:10 GTID last_committed=0 sequence_number=3
#210824 14:41:15 GTID last_committed=0 sequence_number=4
#210824 14:41:11 GTID last_committed=1 sequence_number=5
#210824 14:41:11 GTID last_committed=1 sequence_number=6
#210824 14:41:12 GTID last_committed=1 sequence_number=7

结论

影响主从延迟的因素有很多,比如:主从库负载和IO性能、主库metadata lock、网络带宽、SQL线程无法并行执行,表无主键。

如果您的数据库经常由于SQL线程无法跟上主库多并发事务带来的主从延迟的困扰,不妨升级到MySQL8.0

相关内容