MySQL同步不回放delete_MySQL的delete大表slave回放巨慢的问题分析-爱可生

本文分析了MySQL在无主键的大表上执行无where条件的delete操作导致slave回放超时的问题。通过研究slave在row模式下的重放机制,发现设置`slave_rows_search_algorithms=INDEX_SCAN,HASH_SCAN`能显著提升性能。建议避免全表delete,使用主键,并调整此参数以优化同步性能。" 118807314,7410219,Java实现DBF文件导出解决方案,"['Java', '数据库', '文件操作']
摘要由CSDN通过智能技术生成

原标题:MySQL的delete大表slave回放巨慢的问题分析-爱可生

4973b25213adce392a627e0d63c3e5d5.png

问题

在master上执行了一个无where条件delete操作,该表50多万记录。binlog_format是mixed模式,但transaction_isolation是RC模式,所以dml语句会以row模式记录。此表没有主键有非唯一索引。在slave重放时超过10小时没有执行完成。

分析

首先来了解下slave在row模式下是如何重放relay log的。在row模式下,binlog中会记录DML变更操作的事件描述信息、BEFORE IMAGE、AFTER IMAGE。

delete和update包含了查找操作,基于BI内容搜索找到对应的记录执行相应操作。

基于row模式binlog的重放主要在此函数中进行Rows_log_event::do_apply_event,它根据事件类型调用相应的do_before_row_operations 以delete操作为例

Delete_rows_log_event::do_before_row_operations,此函数会更新sql command计数器(com_delete)

接下来调用Rows_log_event::row_operations_scan_and_key_setup分配需要的内存空间

Prepare memory structures for search operations. If search is performed:

1.using hash search => initialize the hash 2.using key => decide on key to use and allocate mem structures 3.using table scan => do nothing

选择何种搜索策略取决于Rows_log_event::decide_row_lookup_algorithm_and_key的结果,其决策矩阵依赖表的索引信息和slave_rows_search_algorithms参数的设置。 Decision table:

I --> Index scan / search

T --> Table scan

H --> Hash scan

Hi --> Hash over index

Ht --> Hash over the entire table

默认slave_rows_search_algorithms是TABLE_SCAN,INDEX_SCAN,对应函数Rows_log_event::do_index_scan_and_update

如果是INDEX_SCAN,HASH_SCAN,对应函数Rows_log_event::do_hash_scan_and_update

在没有主键的情况下,会遍历binlog每行事件,再用该事件的BI去查找对应的记录,然后变更成对应AI信息。

for each row in the event do{ search for the correct row to be modified using BI replace the row in the table with the corresponding AI}

如果是HASH SCAN over table,会先对binlog事件中的记录执行hash,放到hash表中,再对表中每行记录进行hash,与hash表中的记录对比,条件匹配回放AI部分。

for each row in the event do{ hash the row.}for each row in the table do{ key= hash the row; if (key is present in the hash) { apply the AI to the row. }}

如果是HASH SCAN over index,在有非唯一索引的情况下,对binlog事件中的记录执行hash时,也会将该记录的key保存在一个去重的key列表集合中,然后根据该索引集合去查找记录,对找到的记录执行hash操作并与hash表中的记录对比,如果匹配则回放AI部分。

for each row in the event do{ hash the row. store the key in a list of distinct key.}for each row corresponding key values in the key list do{ key= hash the row; if (key is present in the hash) { apply the AI to the row. }}

从上述分析可以推测在没有主键的情况下Hi的扫描方式会快于Ht和Index scan。

测试

对比slave_rows_search_algorithms在TABLE_SCAN,INDEX_SCAN和INDEX_SCAN,HASH_SCAN两种参数设置下,delete大表哪个效率更高。

CREATE TABLE `ants_bnzbw_temp` ( `accrued_status` varchar(1) COLLATE utf8_bin DEFAULT NULL, `contract_no` varchar(32) COLLATE utf8_bin DEFAULT NULL, `business_date` date DEFAULT NULL, `prin_bal` int(11) DEFAULT NULL COMMENT, `ovd_prin_bal` int(11) DEFAULT NULL COMMENT , `ovd_int_bal` int(11) DEFAULT NULL COMMENT , `int_amt` int(11) DEFAULT NULL COMMENT , `ovd_prin_pnlt_amt` int(11) DEFAULT NULL COMMENT , `ovd_int_pnlt_amt` int(11) DEFAULT NULL COMMENT, KEY `accrued_status` (`accrued_status`) USING BTREE, KEY `contract_no` (`contract_no`) USING BTREE, KEY `business_date` (`business_date`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_binmaster [localhost] {msandbox} (test) > select count(*) from ants_bnzbw_temp;+----------+| count(*) |+----------+| 522490 |+----------+1 row in set (0.15 sec)master [localhost] {msandbox} (test) > delete from ants_bnzbw_temp;Query OK, 522490 rows affected (25.86 sec)

主机slave1

slave_rows_search_algorithms='INDEX_SCAN,HASH_SCAN'

事务执行大约2000s(没有实时追踪事务执行时间)

SET @@SESSION.GTID_NEXT= '00020594-1111-1111-1111-111111111111:237'/*!*/;# at 221356832#180102 14:04:48 server id 1 end_log_pos 221356895 CRC32 0xafdd018f Query thread_id=20 exec_time=25 error_code=0---TRANSACTION 5582, ACTIVE 1447 secmysql tables in use 1, locked 12581 lock struct(s), heap size 319696, 799680 row lock(s), undo log entries 399840

调用栈采样

主机slave2

slave_rows_search_algorithms='TABLE_SCAN,INDEX_SCAN'

事务执行超过11145s,还没执行完成

---TRANSACTION 4520, ACTIVE 11145 secmysql tables in use 1, locked 1622 lock struct(s), heap size 90320, 191792 row lock(s), undo log entries 95896

调用栈采样

结论

通过测试发现使用slave_rows_search_algorithms= INDEX_SCAN,HASH_SCAN 配置在此场景下回放binlog会有大幅性能改善,这种方式会有一定内存开销,所以要保障内存足够创建hash表,才会看到性能提升。

对于此问题的改进建议:

1. 避免无where条件的delete或update操作大表,如果需要全表delete请使用truncate操作

2. 在binlog row模式下表结构最好能有主键

3. 将slave_rows_search_algorithms设置为 INDEX_SCAN,HASH_SCAN ,会有一定性能改善。返回搜狐,查看更多

责任编辑:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值