首页 > 数据库 >Slave SQL线程与PXB FTWRL死锁问题分析

Slave SQL线程与PXB FTWRL死锁问题分析

时间:2024-04-29 09:55:45浏览次数:20  
标签:Slave -- 死锁 线程 SQL kill FTWRL

1. 问题背景

2.27号凌晨生产环境MySQL备库在执行备份期间出现因FLUSH TABLES WITH READ LOCK未释放导致备库复制延时拉大,慢日志内看持锁接近25分钟未释放。

版本:

  • MySQL 5.7.21
  • PXB 2.4.18

慢查询日志:

file

备份脚本中的备份命令:

file

mysql_kill.sh的主要逻辑内容:

file

备份参数:

file

2. 问题复现及分析

2.1 问题分析

file

  • 144是SQL线程,并行复制中的Coordinator线程;
  • 145/146是并行复制的worker线程,145/146worker线程队列中的事务可以并行执行。
  • 162线程是执行innobackup执行的flush tables with read lock;

144 Coordinator线程分发relay log中事务时发现这个事务不能执行,要等待前面的事务完成提交,所以处于waiting for dependent transaction to commit的状态。145/146线程和备份线程162形成死锁,145线程等待162线程 global read lock 释放,162线程占有MDL::global read lock 全局读锁,申请全局commit lock的时候阻塞等待146线程,146线程占有MDL:: commit lock,因为从库设置slave_preserve_commit_order=1,保证从库binlog提交顺序,而146线程执行事务对应的binlog靠后面,所以等待145的事务提交。最终形成了145->162->146->145的死循环,形成死锁。

三个线程相互形成死锁,还是很少见的。

2.2 相关参数为何未生效

--ftwrl-wait-timeout=60 指的是执行FTWRL之前,如果检测到存在长SQL,先等待指定时间(秒),如果超时后还存在长SQL,则备份报错退出。默认为0则表示立即执行。

--ftwrl-wait-threshold=5 指的是执行FTWRL之前,检测长SQL的方法,如果在执行flush前存在已经运行了超过指定时间(秒)的SQL,则将该SQL定义为长SQL,默认60s。

--kill-long-queries_timeout=0 在执行FTWRL后,如果flush操作被阻塞了N秒,则kill掉阻塞它的线程,默认0的情况就是不kill任何阻塞flush的SQL,直到该SQL执行完成。

从上面各个参数的解释,不难看出,--ftwrl-wait-*参数是针对执行FTWRL之前的长SQL检测机制,对于已执行FTWRL时无济于事,--kill-long-*参数则是设置默认值0,不起任何作用。

3. 结论与建议

  • PXB备份中执行FTWRL加全局读锁与SQL线程形成死锁是导致本次从库延迟过高的原因。
  • 启用--kill-long-queries\_type--kill-long-queries\_timeout参数,在检测到flush被阻塞后执行kill掉相关线程的操作。比较暴力,存在较大的风险,若备库无业务访问则可考虑。
  • 启用--safe-slave-backup参数,执行备份时该参数会停掉SQL线程,从而避免死锁的产生。仅建议在无业务访问的备库上执行。
  • 设置MySQL参数slave\_preserve\_commit\_order=0,关闭从库binlog的顺序提交,关闭该参数只是影响并行复制的事务在从库的提交顺序,对最终的数据一致性并无影响,所以如果无特别要求从库的binlog顺序必须与主库保持一致,可以考虑设置slave\_preserve\_commit\_order=0避免死锁的产生。

Enjoy GreatSQL

标签:Slave,--,死锁,线程,SQL,kill,FTWRL
From: https://www.cnblogs.com/greatsql/p/18165043

相关文章

  • Python多线程编程深度探索:从入门到实战
    title:Python多线程编程深度探索:从入门到实战date:2024/4/2818:57:17updated:2024/4/2818:57:17categories:后端开发tags:多线程并发编程线程安全Python异步IO性能优化实战项目第1章:Python基础知识与多线程概念Python简介:Python是一种高级、通用、解释......
  • Java优雅关闭线程池
    一、背景:线程池中有任务正在执行,此时需要关闭或重启应用,池中的任务如何处理,需要考虑任务的损失、关闭速度两个方面考虑。推荐使用Spring提供的线程池:ThreadPoolTaskExecutor,让Spring帮我们管理线程池的生命周期,初始化、监控、扩展、关闭。特别在应用关闭、重启时能实现优雅关闭......
  • Redis单线程,为什么速度快
    Redis是单线程的,但是为什么还那么快完全基于内存的,C语言编写采用单线程,避免不必要的上下文切换可竞争条件使用多路IO复用模型,非阻塞IO例如:bgsave和bgrewriteaof都是在后台执行操作,不影响主线程的正常使用,不会产生阻塞解释一下多路IO复用模型?多路IO复用模型是指利用......
  • 线程池
    线程池1.线程池概念 2.标准库线程池(面试考点) 总结:  3.工厂类创建线程池和基本使用查看代码importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;classTest{publicstaticvoidmain(String[]args){......
  • 不推荐把“线程”注入到Spring、在线程中使用Spring的Bean的方法
    一、不推荐把“线程”注入到spring将线程注入到Spring容器中并不是一个常见的做法,而且通常也不推荐这样做,原因如下:生命周期管理困难:Spring管理的Bean生命周期由Spring容器管理,而线程的生命周期由JVM管理。将线程注入到Spring容器中会导致线程的生命周期与Spring容器的生命周......
  • [Java]线程生命周期与线程通信
    【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)https://www.cnblogs.com/cnb-yuchen/p/18162522出自【进步*于辰的博客】线程生命周期与进程有诸多相似,所以我们很容易将两者关联理解并混淆,一些细节之处确有许多不同,因为线程调度与进程调度虽都由CPU完成,但两者并......
  • 进程和线程
    线程和进程linux中,进程和线程都用task_struct结构体表示,只是进程和线程的区别在于task_struct中的mm和files等资源是否共享。记录层面task_struct中有两个字段记录的是编号pid_tpid;/*processid*/task编号,唯一标识一个taskpid_ttgid;/*threadgroupid*/线程组编......
  • Java 多线程初步总结
    Java多线程程序,进程,线程的基本概念:程序:是为了完成特定的任务,使用某种语言编写的一组指令的集合,是一段静态的代码,静态对象,如Excel,World等。进程:是程序的一次执行多次,或者是正在运行的一个程序,是一个动态的过程,有自身的产生,存在和消亡的过程,即存在生命周期。线程:进程可以进一步......
  • openharmony 多线程的方式有哪些?两个worker线程数据如何通讯、内存如何共享、与Java多
    OpenHarmony操作系统支持多种多线程并发处理策略,以提升应用的响应速度与帧率,以及防止耗时任务对主线程的干扰。以下是OpenHarmony中的多线程方式,以及Worker线程间的数据通讯和内存共享方法,还有它们与Java多线程的区别:OpenHarmony多线程方式Worker线程:OpenHarmony中的Worker是......
  • 哲学家就餐:死锁及解决方案 Java
    本文首发于公众号:腐烂的橘子哲学家就餐问题是计算机科学中的一个经典问题,1971年由荷兰计算机科学家艾兹格·迪科斯彻提出,五台计算机都试图访问五份共享的磁带时会产生问题,后来东尼·霍尔将其重新表述为哲学家就餐问题[1]。问题的详细描述可以参考链接。通俗来讲,就是有五个哲......