达梦DM8数据库运维:批量清理SELECT长查询会话的两种实战脚本(附完整PL/SQL)
达梦DM8数据库运维实战:高效清理SELECT长查询会话的两种PL/SQL方案
当达梦DM8数据库遭遇大量未释放的SELECT查询会话时,系统资源可能被迅速耗尽,导致整体性能断崖式下跌。作为DBA,我们需要在黄金5分钟内快速定位问题源头并实施精准干预。本文将分享两种经过生产环境验证的会话清理方案——从极简应急脚本到带完整审计功能的健壮版本,助你在不同紧急程度下快速夺回数据库控制权。
1. 紧急止血:极简版会话清理脚本
面对CPU使用率突破90%的紧急状况,首要任务是快速释放被占用的资源。这个11行PL/SQL脚本能立即终止所有SELECT类型会话:
BEGIN FOR V_SESSID IN (SELECT SESS_ID FROM V$SESSIONS WHERE SQL_TEXT LIKE 'SELECT%' AND STATE = 'ACTIVE') LOOP SP_CLOSE_SESSION(V_SESSID.SESS_ID); DBMS_OUTPUT.PUT_LINE('已终止会话ID: ' || V_SESSID.SESS_ID); END LOOP; END;关键改进点解析:
- 增加
STATE = 'ACTIVE'条件,避免误杀已闲置会话 - 添加
DBMS_OUTPUT实时反馈操作记录 - 使用
LIKE 'SELECT%'精准匹配查询语句(注意达梦SQL文本大小写敏感)
重要提示:执行前建议先通过
SELECT COUNT(*) FROM V$SESSIONS WHERE SQL_TEXT LIKE 'SELECT%'评估影响范围,避免大规模终止业务会话。
2. 生产级解决方案:带完整审计的健壮脚本
当处于变更窗口期或需要满足合规要求时,推荐使用这个包含预检查、执行日志和结果验证的完整方案:
-- 启用DBMS_OUTPUT日志输出 SET SERVEROUTPUT ON SIZE 1000000; DECLARE V_TOTAL_COUNT NUMBER; V_CLOSED_COUNT NUMBER := 0; V_REMAIN_COUNT NUMBER; CURSOR C_SESSIONS IS SELECT SESS_ID, SQL_TEXT, USER_NAME, CLNT_IP FROM V$SESSIONS WHERE SQL_TEXT LIKE 'SELECT%' AND CREATE_TIME < SYSDATE - 5/1440 -- 运行超过5分钟的会话 ORDER BY CREATE_TIME DESC; BEGIN -- 阶段1:统计待处理会话 SELECT COUNT(*) INTO V_TOTAL_COUNT FROM V$SESSIONS WHERE SQL_TEXT LIKE 'SELECT%'; DBMS_OUTPUT.PUT_LINE('['||TO_CHAR(SYSDATE,'HH24:MI:SS')||'] 待清理会话总数: ' || V_TOTAL_COUNT); -- 阶段2:逐一会话处理 FOR SESS_REC IN C_SESSIONS LOOP BEGIN SP_CLOSE_SESSION(SESS_REC.SESS_ID); V_CLOSED_COUNT := V_CLOSED_COUNT + 1; DBMS_OUTPUT.PUT_LINE('['||TO_CHAR(SYSDATE,'HH24:MI:SS')||'] 已终止会话: ' || 'ID=' || SESS_REC.SESS_ID || ', 用户=' || SESS_REC.USER_NAME || ', 客户端IP=' || SESS_REC.CLNT_IP || ', SQL摘要=' || SUBSTR(SESS_REC.SQL_TEXT,1,60)); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('['||TO_CHAR(SYSDATE,'HH24:MI:SS')||'] 会话终止失败: ' || SESS_REC.SESS_ID || ' - ' || SQLERRM); END; END LOOP; -- 阶段3:结果验证 SELECT COUNT(*) INTO V_REMAIN_COUNT FROM V$SESSIONS WHERE SQL_TEXT LIKE 'SELECT%'; DBMS_OUTPUT.PUT_LINE('['||TO_CHAR(SYSDATE,'HH24:MI:SS')||'] 操作完成报告: '); DBMS_OUTPUT.PUT_LINE(' - 尝试关闭会话数: ' || V_TOTAL_COUNT); DBMS_OUTPUT.PUT_LINE(' - 成功关闭会话数: ' || V_CLOSED_COUNT); DBMS_OUTPUT.PUT_LINE(' - 剩余会话数: ' || V_REMAIN_COUNT); END;2.1 脚本核心增强功能
| 功能模块 | 实现要点 | 业务价值 |
|---|---|---|
| 会话过滤 | 增加运行时长阈值(5分钟) | 避免误杀短时查询 |
| 执行审计 | 记录操作时间、用户、客户端IP | 满足合规审计要求 |
| 异常处理 | 捕获SP_CLOSE_SESSION执行异常 | 确保部分失败不影响整体流程 |
| 结果验证 | 操作前后会话数对比 | 量化清理效果 |
| SQL摘要 | 截取SQL前60字符 | 平衡信息量与可读性 |
3. 高阶应用:动态条件与会话画像
对于需要精细控制的场景,可以通过修改WHERE条件实现多种过滤策略:
-- 示例1:针对特定用户的长时间查询 WHERE USER_NAME = 'APP_USER' AND SQL_TEXT LIKE 'SELECT%' AND LAST_RECV_TIME < SYSDATE - 10/1440 -- 示例2:识别特定IP发起的资源密集型操作 WHERE CLNT_IP = '192.168.1.100' AND SQL_TEXT LIKE 'SELECT%' AND ROWNUM <= 50 -- 限制最大终止数量 -- 示例3:结合V$SQLAREA查找高消耗查询 WHERE SESS_ID IN ( SELECT SESS_ID FROM V$SESSIONS S, V$SQLAREA A WHERE S.SQL_ID = A.SQL_ID AND A.DISK_READS > 10000 )会话分析常用视图组合:
SELECT S.SESS_ID, S.USER_NAME, S.CLNT_IP, A.SQL_TEXT, A.EXECUTIONS, A.ELAPSED_TIME/1000000 AS SECONDS, A.DISK_READS, A.BUFFER_GETS FROM V$SESSIONS S JOIN V$SQLAREA A ON S.SQL_ID = A.SQL_ID WHERE S.STATE = 'ACTIVE' ORDER BY A.ELAPSED_TIME DESC;4. 操作风险管理与最佳实践
4.1 执行前的必要检查
会话重要性评估:
-- 识别关键业务会话 SELECT USER_NAME, COUNT(*) FROM V$SESSIONS WHERE SQL_TEXT LIKE 'SELECT%' GROUP BY USER_NAME ORDER BY COUNT(*) DESC;锁定检测:
-- 检查是否存在被锁定的关键表 SELECT OBJECT_NAME, SESS_ID, LOCKED_MODE FROM V$LOCK L, DBA_OBJECTS O WHERE L.TABLE_ID = O.OBJECT_ID AND O.OWNER = '核心业务用户';
4.2 执行后的监控要点
资源释放验证:
# Linux系统级监控 watch -n 1 "top -b -n 1 | head -15"达梦性能视图检查:
-- 实时系统负载 SELECT * FROM V$SYSTEM_EVENT WHERE EVENT LIKE '%CPU%' ORDER BY TOTAL_WAITS DESC;
经验之谈:在大型金融系统中,建议先终止非核心业务时段的会话(通过CREATE_TIME判断),保留交易时段的会话,并配合
SP_DETACH_SESSION临时隔离而非直接关闭关键会话。
应急预案对比表:
| 场景特征 | 推荐方案 | 优势 | 风险控制措施 |
|---|---|---|---|
| 上班时间CPU爆满 | 极简版脚本 | 响应速度快(秒级) | 提前与业务方确认可终止范围 |
| 夜间批量作业堆积 | 健壮版脚本 | 完整审计轨迹 | 设置单次最大终止数量(ROWNUM) |
| 未知来源的异常连接 | 增加IP过滤条件 | 精准打击问题源头 | 保留前N条会话供取证分析 |
| 关键业务表锁等待 | 结合V$LOCK视图过滤 | 避免连锁反应 | 优先终止非DML会话 |
