SQL生产慢查询应急方案_快速止血与回滚策略

2次阅读

慢查询应急需“稳准狠”:5分钟内定位、3分钟干预、1分钟验证;优先kill会话止血,禁盲目加索引;用sql改写、hint、限流兜底;所有操作须留痕、可回退、可验证。

SQL生产慢查询应急方案_快速止血与回滚策略

遇到SQL生产慢查询,第一反应不是查原因,而是快速止血——阻断对数据库的持续冲击,保障核心业务可用。关键在“快”:5分钟内识别、3分钟内干预、1分钟内验证效果。

一、实时定位罪魁SQL(不依赖历史日志)

直接登录数据库服务器,用系统视图或命令秒级抓取正在运行的长耗时SQL:

  • mysql:执行 SHOW PROCESSLIST,重点关注 Time > 60State = “Sending data” / “Copying to tmp table 的连接;配合 SELECT * FROM information_schema.PROCESSLIST WHERE TIME > 60;
  • postgresql:查询 pg_stat_activity,筛选 state = ‘active’backend_start ,再按 backend_start 倒序;加 pg_blocking_pids(pid) 快速判断是否被阻塞
  • oracle:查 v$sessionv$sql 关联,用 sql_idlast_call_et > 60 定位活跃慢SQL

二、立即终止(KILL)而非等待超时

确认SQL无业务强依赖(如非事务关键路径、非金融最终一致性写入),果断终止会话:

  • MySQL:执行 KILL [id](id 来自 PROCESSLIST 中的 Id 字段);若担心误杀,先 KILL QUERY [id] 只终止当前语句,保留连接
  • PostgreSQL:执行 select pg_terminate_backend(pid);若只想取消当前查询,用 pg_cancel_backend(pid)
  • 注意:KILL 操作本身几乎无延迟,但需确保有对应权限(如 MySQL 的 PROCESS + SUPER 权限)

三、临时降级:加索引?先别动!用覆盖手段兜底

线上加索引可能锁表、阻塞DML,风险高。应急阶段优先用更安全的“逻辑兜底”:

  • 改写SQL:去掉 SELECT *,明确字段;拆分大 LIMIT OFFSET(如 LIMIT 10000,20 → 改为基于主键/时间戳的游标分页)
  • 加查询提示(Hint):MySQL 用 /*+ MAX_EXECUTION_TIME(3000) */ 强制超时;PG 用 SET LOCAL statement_timeout = ‘3s’(需在事务内设置)
  • 前置限流:在应用层(如 nginx、API 网关)对该接口做 QPS 限流(如限制为 1/s),避免重试风暴

四、回滚必须可验证、可逆、带记录

任何变更操作(包括 KILL、参数调整、SQL改写上线)都必须留痕并验证回退路径:

  • 执行前,用 mysqlbinlog / pg_waldump 记录当前 binlog/wal 位置,或截图 SHOW MASTER STATUS / SELECT pg_current_wal_lsn()
  • KILL 后立刻检查:QPS 是否回升、连接数是否回落、错误率是否下降;用 pt-query-digest 或 PG 的 pg_stat_statements 验证该SQL是否消失
  • 所有操作写入值班日志(含时间、执行人、SQL原文、KILL ID、影响行数估算),禁止口头交接

慢查询应急不是技术炫技,是稳准狠的外科手术——止血比缝合重要,记录比解释重要,验证比执行重要。

text=ZqhQzanResources