自动kill慢查询

在生产环境中,DB服务器经常会被并发的慢查询压挂,因此事前进行sql审核避免烂SQL很重要。万一不小心慢sql还是跑到线上,并且并发还不小,这是dba肯定会收到告警。dba上线处理第一时间是定位并kill慢查询,避免慢查询其他正常的事务。本文主要围绕kill展开,并附带介绍几种相关的timeout参数和实现机制。

kill指令

kill的语法如下:kill [connection|query] thread_id,通过kill命令可以kill一个查询或kill一个连接。一般而言,每个用户只能查看和终止自己用户的连接和查询,若用户具有process权限,则可以查看所有线程,具有super权限,可以查看和终止所有用户的连接和查询。假设有两个会话A和B,A的thread_id为xxx,A会话执行查询,B会话分别执行kill query xxx和kill xxx,会话A会分别收到1317和2013错误。

mysql> select count(*) from test_slow where 1=1;
ERROR 1317 (70100): Query execution was interrupted
mysql> select count(*) from test_slow where 1=1;
ERROR 2013 (HY000): Lost connection to MySQL server during query   

通过mysql客户端进行操作,除了发送kill指令,还可以通过ctrl+c来终结自己。这里的原理很简单,mysql客户端里面有一个信号捕获线程,监听到SIGINT后,创建一个连接,然后发送kill命令到服务端,将自己终结。通过gdb调试时,为了避免gdb对信号的影响,通过命令设置即可,命令如下:

handle SIGINT nostop print pass

kill实现原理

mysqld收到kill命令后,会将对应的线程实例thd设置为kill状态,若为kill_connection,会主动断开socket。因此对于kill connection 操作,线程马上会kill,但是对于kill query,则查询可能不能立即结束,因为查询可能正在运行过程中。因此,在mysqld的代码中的关键节点都会调用trx_is_interrupted函数判断自身的状态是否为killed,若是,则报错返回,终止执行。到底mysqld在哪些地方会进行检查,这里列出官方的文档,说明如下:

• In SELECT, ORDER BY and GROUP BY loops, the flag is checked after reading a block of rows. If the kill flag is set, the statement is aborted.

• During ALTER TABLE,
the kill flag is checked before each block of rows are read from the original
table. If the kill flag was set, the statement is aborted and the temporary
table is deleted.

• During UPDATE
or DELETE operations, the kill flag is checked after each block read and after
each updated or deleted row. If the kill flag is set, the statement is aborted.
Note that if you are not using transactions, the changes are not rolled
back.

kill自动化

如果每次查询都需要dba人工去触发,那么遇到问题时,可能处理没那么及时,如果能自动化的kill慢查询则能将影响降到最低。在jdbc中通过接口Statement.setQueryTimeout(int) 即可实现。这个原理其实与mysql客户端通过ctrl+c
kill查询类似,只不过这种方式是通过超时实现。设置一个定时器,有一个线程定时不停地判断定时器事件有没有触发,达到触发点后,再发送kill查询到服务端,实现kill查询的目的。这种方式虽然能自动化,但这个接口调用控制权还是在开发手中,而且一般情况下,开发一定都认为自己的查询时没有问题的,肯定不会超时,所以这个接口是否被调用无法控制。那么遇到问题后,DB还是一样会挂,还是需要dba人工处理。因此在alimysql内核也做了一套类似的功能,通过参数max_statement_time可以控制当前会话和所有会话的超时时间。只要超时,mysql内部会调用接口awake接口将对应的thd状态设置为killed,达到kill query或kill connection的目的。

几种超时参数

除了我们上面提到的statement
timeout,jdbc中常见的超时参数还有connectTimeout和socket timeout。

connectTimeout:和数据库服务器建立socket连接时的超时,单位:毫秒。

socket timeout: socket操作(读写)超时

具体而言,jdbc通过设置socket的属性来实现超时目的,不同的JDBC驱动其配置方式会有所不同。 socket连接时的timeout:通过Socket.connect(SocketAddress
endpoint, int timeout)设置;socket读写时的timeout:通过Socket.setSoTimeout(int timeout)设置,采用阻塞IO模型,如果不设置socket
timeout或connect timeout,应用多数情况下是无法发现网络错误的。因此,当网络错误发生后,在连接重新连接成功或成功接收到数据之前,应用会无限制地等下去。当然,操作系统层面,也会有socket timeout设置。相关的配置参数如下:

tcp_keepalive_time:TCP连接在idle指定时间后,内核才发起probe

tcp_keepalive_probes:TCP发送keepalive探测以确定该连接已经断开的次数

tcp_keepalive_intvl:探测消息发送的频率

因此,探测(tcp_keepalive_time + tcp_keepalive_intvl * tcp_keepalive_probes)时间后,若还不能连上,则断开连接。

这些参数可以修改:

/proc/sys/net/ipv4/tcp_keepalive_time
/proc/sys/net/ipv4/tcp_keepalive_intvl
/proc/sys/net/ipv4/tcp_keepalive_probes

参考文献

http://astar.baidu.com/forum/forum.php?mod=viewthread&tid=363

http://dev.mysql.com/doc/refman/5.1/en/kill.html

http://m.blog.csdn.net/blog/xieyuooo/39898449

http://blog.sina.com.cn/s/blog_a2d4803001013hrk.html

时间: 2024-10-14 00:12:31

自动kill慢查询的相关文章

python监听windows上w3wp进程,如果cpu>=95%则自动kill掉

因为最近服务器前端虽然加了负载均衡,但是后端windows主机偶尔还有因为服务进程cpu到99这种情况导致服务不可用,虽然这个不用第一时间处理,但是也需要手工登录进行进程的kill,windows下可以通过dos脚本写个.bat脚本实现这个功能,并通过配置调用这个.bat脚本,但是我试过几次感觉不太适合我 所以通过python写一个脚本并用py2exe转换成.exe程序放在几台windows上,因为不可能每台server都手工部署下python环境. 代码如下: import psutil im

自动生成SQL查询、删除、更新、插入语句

自动生成sql语句 select 'update  ' || t.table_name || ' a  set ' ||       (select wm_concat('a.' || a.column_name || '=' || Chr(39) || '{' ||                         Abs(Rownum - 1) || '}' || chr(39) || '   --' ||                         a.Comments || Chr(1

自动生成 Lambda查询和排序,从些查询列表so easy

如下图查询页面,跟据不同条件动态生成lambda的Where条件和OrderBy,如果要增加或调整查询,只用改前台HTML即可,不用改后台代码 前台代码: 1 <div style="padding-bottom: 5px;" id="queryForm"> 2 3 <span>员工姓名:</span><input type="text" emptytext="ddd" data-op

Jenkins任务启动的后台进程被自动kill

在Jenkins的使用中,遇到过的一个场景是:在web代码更改之后,能自动的部署到测试服务器,我们写了run.sh脚本来重启服务,在使用Jenkins的任务自动跑这个脚本后发现,服务没有起来.开始以为是run.sh脚本的问题,但是直接执行是没有问题的:之后一直查运行环境差异,发现也不是这个原因:到后来才怀疑到Jenkins任务结束时候自动关掉了所有的子进程.通过以下shell脚本片段解决了问题: #临时改变BUILD_ID值,使得Jenkins不会找到并结束掉run.sh启动的后台进程OLD_B

MySQL事件自动kill运行时间超时的SQL

delimiter $create event my_long_running_trx_monitoron schedule every 1 minutestarts '2015-09-15 11:00:00'on completion preserve enable dobegin declare v_sql varchar(500); declare no_more_long_running_trx integer default 0; declare c_tid cursor for se

同步的数据过大,导致shareplex超时,并自动kill掉了同步会话

数据库迁移,其中有个数据量较大的表的索引,在迁移的时候出现,同步超时的情况 Notice 2014-08-05 15:14:54.856107 14240 3892311808 Poster: Operation ODR_DDL on table "CMUSER"."TBL_CM_PACKAGEPUSHSESSION_R" is taking longer than 5 seconds. SID/s erial: 719/35771 Subqueue: 1. (po

[原创] CQ(clear quest)自动执行查询并将查询结果通过email发送的实现

负责的项目有时候会被项目经理找来催,原来又没有及时的去搜索CQ... 于是这两天自己实现了一下能自动执行CQ查询的脚本,同时还能降查询结果发送到我的邮箱.分享一下吧: 简单说明一下: 1)其实是两个比较独立的的功能拼凑到一块实现的, 一个功能是CQ的登陆和查询, 看函数logonDMS()和DoQuery(): 一个功能是发送email,看函数sendmail(). 2)是用CQ的perl接口实现的,执行的时候不能用原生的perl执行, 必须用CQ安装目录下的CQPerl.exe 来执行. 好了

【iOS】FMDB封装,查询自动mapping

sqlite几乎所有的App都会用到,但是系统自带的sqlite API是用C语言写的,非常不友好,用起来非常不便,通常我们使用第三方封装好的工具,例如:FMDB(https://github.com/ccgus/fmdb) FMDB的提供了一种更简单,方便的API,并且还提供了线程安全的队列FMDatabaseQueue用于数据库的读写,关于FMDB的使用,参见github上的描述 在使用FMDB查询表的时候的时候我们一般用下面方式 1.定义一个数据模型PersonModel @interfa

ORACLE 常用SQL查询

一.ORACLE的启动和关闭 1 .在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su  -  oracle a.启动ORACLE系统 oracle > svrmgrl SVRMGR > connect internal SVRMGR > startup SVRMGR > quit b.关闭ORACLE系统 oracle > svrmgrl SVRMGR > connect internal SVRMGR > shutdown