当程序遇到慢sql

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun_ashe/article/details/82996633

问题

某天某业务RD咨询我说,如果程序连接数据库,执行查询时,sql执行的很慢,为了避免数据库长时间执行这个慢语句,以及避免业务线程处于长时间等待状态,通过另外一个线程执行close操作,数据库是否还会继续把这个sql执行下去呢?

一开始我回复说数据库线程会退出,后面一想,是有问题的,这涉及到一个正在执行sql的数据库链接是如何检测自己是否应该退出的。

解释

首先,站在dba的角度来想,当我们发现数据库中存在慢语句时,如果想杀掉它,一般是使用kill命令,通过kill connection或者kill query都可以使这个慢查询退出,关于kill的内部原理通过另外一篇文章来解释。
再者,如果是我们手动通过mysql客户端执行一条sql,发现执行了很长时间,可以通过control+c来断开,这又是如何断开的呢?其实通过打开general_log就能发现,当发送control+c时,其实客户端会执行如下sql语句

2018-10-10T14:14:19.044128+08:00	   27 Query	select count(*) from ashe a,ashe b where a.name=b.name
2018-10-10T14:14:20.336758+08:00	   28 Connect	[email protected] on  using TCP/IP
2018-10-10T14:14:20.337000+08:00	   28 Query	KILL QUERY 27
2018-10-10T14:14:20.337292+08:00	   28 Quit

这是MySQL-5.7的客户端,和5.6版本有区别,5.6应该是kill connection,客户端会自动退出。说白了,并不是自己断开,而是新建一个链接来执行kill操作的。

答案?

首先来说明下RD自己提出的方法,是通过另外一个线程进行close,这种方法确实可以关闭客户端到server的tcp链接,但是并不会影响到sql的继续执行,因为数据库内部在执行时,并没有检测socket链接是否存活。

所以,方法我觉得有如下几种

另开一个线程,进行kill

首先可以通过连接句柄拿到这个链接的processlist id,再另开一个线程获取新的数据库链接,进行kill query操作。这个方法和我们control+c是一样的,

设置max_execution_time

在执行sql之前,可以通过设置线程级别的max_execution_time,当超时后,此线程自动退出执行。

猜你喜欢

转载自blog.csdn.net/sun_ashe/article/details/82996633