binlog write threshold exceeded

1.问题描述

        线上报警:事务无法提交。binlog(1610646347 bytes) write threshold exceeded

2.分析问题

        (1)背景描述

        MariaDB集群

目前MariaDB binlog_write_threshold限制是1.6G,Percona无限制。max_binlog_size默认最大是1G,但是上面参数限制了最大binlog size。

        (2)binlog日志分析

        在开启binlog的情况下,prepare阶段,会对redo log进行一次刷盘操作(innodb_flush_log_at_trx_commit=1),确保对data页和undo 页的更新已经刷新到磁盘;commit阶段,会进行刷binlog操作(sync_binlog=1),并且会对事务的undo log从prepare状态设置为提交状态(可清理状态)。通过两阶段提交方式(innodb_support_xa=1),可以保证事务的binlog和redo log顺序一致。二阶段提交过程中,mysql_binlog作为协调者,各个存储引擎和mysql_binlog作为参与者。故障恢复时,扫描最后一个binlog文件(在flush阶段,判断binlog是否超过阀值,进行rotate binlog文件,rotate的binlog文件中对应的事务一定是已经提交的,处于prepared的事务的binlog还没有刷进来,因为还没进入ordered_commit函数),提取其中的xid;重做检查点以后的redo日志,读取事务的undo段信息,搜集处于prepare阶段的事务链表,将事务的xid与binlog中的xid对比,若存在,则提交,否则就回滚。

        (3)问题分析

当超过1GB文件的时候,会自动切到新的binlog,执行某些大事务,为了事务的完整性,binlog要等事务执行完成后切换,所以binlog可能大于1GB。

从展示出来的数据,我推断代码中有大事务,一次提交。

1610646347 bytes = 1.5000313 gb

3.解决

3.1主要思路

避免大事务SQL执行。

需要重新评估当前事务涉及SQL执行时涉及修改表的数据量,采用limit 方式循环执行提交。将一个大事务分割为多个小事务。

3.2扩展问题

        大事务大数据引发的OOM,当把所有的数据一次性加载到内存,放到arraylist,arraylist一次扩容2倍,dump堆内存,确认了问题所在。最后解决方法也是用limit分页,但是limit分页在集群中需要注意重复消费的问题。

 

发布了182 篇原创文章 · 获赞 45 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/u014172271/article/details/102081820