【Oracle】记排查sh脚本调用SQL执行卡顿的排查总结

整个过程分为 OS层(操作系统) 和 DB层(数据库) 两个阶段。


第一阶段:OS层排查(发现异常进程)

步骤 1:发现可疑进程

  • 目标:查找目标脚本进程。

  • 执行命令 :

    bash 复制代码
    ps -ef | grep get_b
  • 发现 :父进程 102374(/bin/sh)和子进程 102376(sqlplus)自 Aug31 起运行,CPU累计时间为 00:00:00。


步骤 2:查看父进程内核态等待状态

  • 目标:确认父进程卡在什么内核调用上。

  • 执行命令 :

    bash 复制代码
    ps -o pid,stat,wchan=WIDE-WCHAN-COLUMN -p 102374
  • 回显 :S(可中断睡眠) + do_wait(等待子进程退出)。

  • 结论 :父进程自身正常,是在等待子进程(102376)结束。


步骤 3:确认父子进程关系

  • 目标:查看父进程下的子进程详情。

  • 执行命令 :

    bash 复制代码
    ps -ef | grep 102374
  • 发现 :子进程 102376 是 sqlplus -S(静默SQL*Plus客户端)。


第二阶段:DB层深度排查(推翻OS层"杀进程"的误判)

步骤 4(关键转折):在数据库内查看会话真实状态

  • 目标:确认SQL在数据库内部的真实状态(是卡死还是在干活)。

  • 执行命令(在SQL*Plus或PL/SQL中以DBA身份执行) :

    sql 复制代码
    SELECT s.sid, s.serial#, s.status, s.sql_id, 
           s.event, s.wait_class, s.seconds_in_wait
    FROM v$session s
    WHERE s.process = '102376'   -- 对应OS进程号
      AND s.program LIKE '%sqlplus%';
  • 关键发现 :STATUS=ACTIVE,WAIT_CLASS=User I/O。

  • 结论 :数据库正在积极执行I/O操作(读数据/写临时表空间),绝对不能 在OS层执行 kill -9,否则会导致数据库回滚风暴。


步骤 5:查看SQL执行进度(长期操作监控)

  • 目标:确认SQL完成百分比。

  • 执行命令 :

    sql 复制代码
    SELECT opname, target_desc, sofar, totalwork, 
           ROUND(sofar/totalwork*100,2) AS pct_complete,
           elapsed_seconds, time_remaining
    FROM v$session_longops
    WHERE sid = <步骤4查到的SID>
      AND sofar < totalwork
    ORDER BY start_time DESC;
  • (可能的结果):如果进度不增长,配合步骤6进一步诊断。


步骤 6:确认I/O挂起(最终诊断)

  • 目标 :当发现 seconds_in_wait 持续增加且不归零时,查看具体等待事件和等待的文件号。

  • 执行命令 :

    sql 复制代码
    SELECT event, seconds_in_wait, state, 
           p1, p1text,   -- p1代表文件号
           p2, p2text    -- p2代表块号
    FROM v$session 
    WHERE sid = <步骤4查到的SID>;
  • 发现 :seconds_in_wait 持续增长,证明单次I/O请求挂起(存储响应极慢或磁盘故障)。


步骤 7(可选):定位卡住的物理数据文件

  • 目标:找出P1文件号对应的具体文件(用于联系存储工程师)。

  • 执行命令 (如果P1指向数据文件):

    sql 复制代码
    SELECT file_id, file_name, tablespace_name
    FROM dba_data_files
    WHERE file_id = <步骤6查到的P1值>;
  • (如果指向临时表空间) :

    sql 复制代码
    SELECT file_id, file_name, tablespace_name
    FROM dba_temp_files
    WHERE file_id = <步骤6查到的P1值>;

步骤 8(可选):抓出正在执行的完整SQL内容

  • 目标:保存SQL供后续优化参考。

  • 执行命令 :

    sql 复制代码
    SELECT sql_fulltext
    FROM v$sql
    WHERE sql_id = '<步骤4查到的SQL_ID>';

最终解决方案(执行的动作)

鉴于确诊为 存储I/O挂起 且 sofar 无推进,决定放弃本次执行。禁止使用OS层的 kill -9 102376,改为在数据库端优雅取消SQL。

最终执行命令(在数据库中):

sql 复制代码
-- 假设步骤4查到的 SID=123, SERIAL#=45678
ALTER SYSTEM CANCEL SQL '123, 45678';

执行效果:

  • 数据库立即中止当前I/O调用,会话返回 ORA-01013 错误并退出。
  • OS层的子进程 102376 自动终止,父进程 102374 收到子进程退出信号,自动结束 do_wait 并退出。
  • 整个进程树彻底清理,且无回滚灾难风险。

附加:事后预防建议(未执行,但建议后续添加)

如果脚本将来需要防止此类长时间挂起,可在OS层脚本中修改,增加 timeout 命令限制SQL*Plus的执行时长:

bash 复制代码
timeout 3600 sqlplus -S user/pass@db @script.sql

(超过1小时自动强制终止,避免积累僵尸卡住进程。)


总结核心原则 :只要 ps 看到 sqlplus 挂起,第一反应永远不是 kill -9 ,而是进入数据库查 v$session。User I/O 是干活状态,Concurrency 是锁等待,只有当 seconds_in_wait 疯涨且进度为0时才考虑 ALTER SYSTEM CANCEL。

相关推荐
Web3&Basketball28 分钟前
实测Gemini4Argon:ERQA 87%登顶长程任务榜
数据库·python·大模型·多模态·gemini·长上下文·推理优化
xiaogai_gai41 分钟前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
注塑机数据采集联网1 小时前
注塑机数据采集网关对接MES系统数字化技术方案
大数据·网络·数据库·物联网·数据挖掘·数据分析
像风一样自由20201 小时前
56.实战PostgreSQL-pgvector-FastAPI构建轻量级RAG
数据库·人工智能·postgresql·大模型·fastapi·智能体
User_芊芊君子2 小时前
KFS异构同步_260条链路DDL自动转换解析
数据库·ai·大模型
xiancai_xianyu2 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
cc5725026532 小时前
2027校招准备:数据科学与大数据技术专业转产品数据运营,PRD与SQL怎么安排?
大数据·sql·墨刀
Zucker n2 小时前
一款适合研究生科研工作安排的日历
linux·数据库·python
Sharewinfo_BJ3 小时前
Power BI沿袭视图详解:从看懂链路到做影响分析
数据库·数据分析·智信bi·上北智信
l1t3 小时前
DeepSeek总结的 DuckDB 2.0 中更简洁的变量语法
数据库·sql