长时间运行的查询 / 作业
症状
某个查询/作业已运行数小时仍未结束;它消耗资源或影响其他操作。
1. 捕获查询及其运行时长
是哪个查询、已运行多久、哪个用户/应用?
Oracle
SELECT sid, serial#, sql_id, last_call_et/60 running_min, username FROM v$session WHERE status='ACTIVE' AND type='USER' ORDER BY last_call_et DESC;PostgreSQL
SELECT pid, now()-query_start dur, usename, query FROM pg_stat_activity WHERE state='active' ORDER BY query_start;MySQL
SELECT id, user, time, state, info FROM information_schema.processlist WHERE command='Query' ORDER BY time DESC;SQL Server
SELECT session_id, total_elapsed_time/1000 sec, status, command FROM sys.dm_exec_requests WHERE session_id IN (SELECT session_id FROM sys.dm_exec_sessions WHERE is_user_process = 1) ORDER BY total_elapsed_time DESC;MongoDB
db.currentOp({ active: true, secs_running: { $gt: 60 } })2. 是在推进还是卡住了
它真的在运行,还是在等待锁?查看进度指标(Oracle v$session_longops、PG pg_stat_progress_* 视图)。若在等待,请转到“阻塞与锁危机”应急手册。
Oracle
SELECT sid, opname, sofar, totalwork, ROUND(sofar/NULLIF(totalwork,0)*100,1) pct, time_remaining FROM v$session_longops WHERE sofar<totalwork;PostgreSQL
SELECT * FROM pg_stat_progress_create_index; -- or pg_stat_progress_vacuum / _cluster / _analyze3. 决定:等待还是取消
若正在推进且很快就会完成,就等待(取消带来的回滚代价可能使其耗时更长)。若已卡住、运行有误或影响生产,就终止它。取消前要考虑回滚时间。
4. 必要时终止
优先只取消查询(保留会话);若无效,再终止会话。
Oracle
ALTER SYSTEM CANCEL SQL 'sid,serial#'; -- 18c+; otherwise KILL SESSIONPostgreSQL
SELECT pg_cancel_backend(pid); -- otherwise pg_terminate_backend(pid)MySQL
KILL QUERY <id>;SQL Server
KILL <session_id>;MongoDB
db.killOp(<opid>)5. 永久修复
优化查询(索引、计划、分页/分批),将繁重作业移到非高峰时段,必要时分块运行。对于周期性报表,考虑使用物化视图 / 只读副本。