首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >生产环境惊魂:慢SQL导致CPU飙升至99%?教你用Python写个“自动清道夫”!

生产环境惊魂:慢SQL导致CPU飙升至99%?教你用Python写个“自动清道夫”!

作者头像
俊才
发布2026-05-26 19:57:15
发布2026-05-26 19:57:15
670
举报
文章被收录于专栏:数据库干货铺数据库干货铺

大家估计都经历过这样的“紧张时刻”:

周一早上刚到公司,运维群里突然炸锅:“生产环境数据库CPU飙升到100%了!”、“系统响应极慢,接口大量超时!”、“前端页面直接白屏了!”……

打开监控一看,好家伙,数据库里堆积了几百个执行时间超过几分钟的慢查询。这些“流氓SQL”不仅占满了数据库连接池,还疯狂消耗CPU资源,导致正常的业务请求根本挤不进去。

面对这种“慢SQL风暴”,手动一条条去KILL显然来不及。今天,我们就来分享一个实战技巧:如何用Python写一个轻量级的“慢SQL自动查杀脚本”,定时清理垃圾会话,为数据库“止血”!需要的同学可以联系我获取完整脚本。

一、核心思路:监控+筛选+查杀

我们的目标很明确:在后台默默运行,每隔一段时间检查一次数据库,发现符合条件的“坏分子”就直接干掉。

整体逻辑分为三步:

  • 建立连接:使用Python的pyodbc库连接SQL Server数据库
  • 精准筛选:通过系统视图(如sys.dm_exec_requests)找出运行时间过长、且包含特定关键词的SQL会话
  • 果断查杀:遍历筛选出的会话ID,执行KILL命令释放资源,并记录到日志中方便复盘

二、实战拆解与避坑指南

在编写这个脚本的过程中,有几个极易踩坑的技术点,这里特意把核心代码片段拎出来给大家讲讲。

1. 如何精准揪出“慢SQL”?

我们需要查询SQL Server的动态管理视图。这里有一个非常关键的细节:获取SQL文本时,一定要做类型转换!

代码语言:javascript
复制
-- 核心查询片段
SELECT s.session_id, DATEDIFF(MINUTE, r.start_time, GETDATE()) AS duration_minutes, 
       CAST(t.text AS NTEXT) AS sql_text  -- 重点:强转为NTEXT
FROM sys.dm_exec_sessions s
INNER JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.is_user_process = 1
  AND DATEDIFF(MINUTE, r.start_time, GETDATE()) >= 20 -- 运行超过20分钟
  AND t.text LIKE '%select%' -- 包含特定关键词

避坑点:如果不将t.text强转为NTEXT类型,Python的pyodbc驱动默认只会截取前255个字符。到时候你查杀了会话,却在日志里看不到完整的SQL语句,排查问题时就会一脸懵。

2. 为什么执行KILL命令会报错?

很多同学可能和我一样,在写好查杀逻辑cursor.execute("KILL 55")后,运行脚本却抛出了异常:“无法在用户事务内部使用KILL命令”。

这是因为pyodbc默认开启事务模式,而KILL这种系统级命令是不能包裹在普通事务里的。

解决方法:在建立数据库连接后,开启自动提交模式。

代码语言:javascript
复制
conn = pyodbc.connect(conn_str)
conn.autocommit = True  # 开启自动提交,让KILL命令立即生效

3. 完整的查杀与日志记录

当脚本抓到“现行”后,不仅要杀掉它,还要把“案发现场”记录下来。

代码语言:javascript
复制
# 查杀逻辑片段
kill_sql = f"KILL {session_id}"
cursor.execute(kill_sql)
# 记录完整SQL到日志,方便后续甩锅...啊不,复盘
log_msg = (f"成功杀掉会话! SessionID: {session_id}, "
           f"运行时长: {duration}分钟\n"
           f"执行的SQL语句:\n{full_sql_text}")
logging.warning(log_msg)

三、总结与建议

这个脚本虽然没有多少行代码,但在生产环境紧急救火时非常管用。它可以作为一个守护进程在后台运行,充当数据库的“保安”。

最后给几点生产环境的使用建议:

  • 先观察,后动手:刚开始可以将脚本设置为“只打印不查杀”(Dry Run模式),观察几天,确保不会误杀核心业务的正常长事务。
  • 精准匹配:筛选条件尽量加上program_name(程序名称)或特定的SQL前缀,避免误伤后台正常的统计任务。
  • 日志轮转:记得配置日志文件的大小和保留天数,防止日志把磁盘写满。

希望这个小工具能帮大家远离半夜被报警电话叫醒的烦恼!如果你觉得有用,欢迎点赞、在看、转发三连!🚀

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据库干货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档