MySQL中max_execution_time引发的血案
2021/5/8 2:25:36
本文主要是介绍MySQL中max_execution_time引发的血案,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、场景问题
今天MySQL存储节点突然收到cpu持续100%的报警,持续时间长达数个小时。在控制台中通过show processlist查看当前进程,发现很多一模一样的SQL一直在运行,执行时间都超过数个小时。
二、疑问分析
一般对用户而言,都会有一个超时时间,接口不可能无限等待,如果一直等待体验也不好。所以都会设置一个超时时间,不管是前端请求的超时时间,亦或者是nginx的请求超时时间。但大家思考过这样一个场景没,当http的请求断开,那接口中涉及到的SQL是会继续执行,还是会断开链接呢?
三、寻根问题
答案是肯定的,因为这条SQL已经在数据库执行了,除非应用程序提交kill的命令,否则它会一直执行到超时为止。
那这个超时的时间主要由哪个字段决定呢?我们来看看MySQL5.7的官网说明:
MySQL5.7是由:max_execution_time决定,如果设置为0,那就是不做任何限制,会一直执行到天荒地老。。。
本文讨论的范围为select查询操作,MySQL为5.7,其它版本和类型不再本文的讨论范围之内。
四、解决方案
一般来说数据库层面的配置,我们普遍会设置一个可以容忍的最大值,因为要兼容所有的应用,不可能针对单独的应用或者接口来设置。那问题又来了,我们如何设置应用级别和接口级别的查询超时呢?
4.1 应用超时
我们以druid连接池为例,如果想要设置应用级别的查询超时,可以添加如下配置:
#SQL执行超时时间,针对所有CRUD spring.datasource.druid.query-timeout=300
但这种配置有个弊端就是,它生效的范围不仅仅selete,包含CRUD所有种类型。
因为druid目前没有提供针对于select查询超时时间设置,如果想要单一类型生效可以做一些自己的封装。具体的封装方式一般有2种,一种是修改源代码,对特殊的select进行修改,另外一种是在mybatis层面,代理执行的时候对属于select类型的进行拦截修改。博主比较推荐第二种方式,代码的侵入性比较低,第一种后期如果对druid升级会有麻烦。
4.2 接口超时
接口级别的可以加上setQueryTimeout属性,给SQL查询设置一个超时时间。这个属性其实和应用全局的形式是一样的,但是他是作用在具体的一个SQL层面,我们只需要给select类型设置这个字段就可以了。
五、题外话【产品】
还有一点想跟大家分享的是,属于非技术层面的。像上面提到的那个问题,问什么线上会出现那么多一模一样的SQL,一直不断的再执行呢?因为用户一旦发现哪个操作很久都没有结果出来,就会不断的一直重试,然后情况越来越坏,这也是为什么一旦系统出现问题,就会马上爆发出来,直到系统宕机。所以在产品这个维度也需要进行些优化,做一些限制。
六、总结
今天给大家分享了三种设置SQL查询超时的方法:数据库max_execution_time、druid连接池的spring.datasource.druid.query-timeout、接口级别的setQueryTimeout。除了技术层面,产品设计方面也需要考虑权衡。今天的分享就到这边了,林老师代码学编程,今天你学习了嘛。
公众号:林老师带你学编程
网站:www.wolzq.com
代码无非增删改查,关注老师给你Coding
林老师带你学编程:http://www.wolzq.com
这篇关于MySQL中max_execution_time引发的血案的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-04部署MySQL集群项目实战:新手入门教程
- 2024-11-04如何部署MySQL集群资料:新手入门指南
- 2024-11-02MySQL集群项目实战:新手入门指南
- 2024-11-02初学者指南:部署MySQL集群资料
- 2024-11-01部署MySQL集群教程:新手入门指南
- 2024-11-01如何部署MySQL集群:新手入门教程
- 2024-11-01部署MySQL集群学习:新手入门教程
- 2024-11-01部署MySQL集群入门:新手必读指南
- 2024-10-23BinLog入门:新手必读的MySQL二进制日志指南
- 2024-10-23Binlog入门:MySQL数据库的日志管理指南