数据库管理-第306期 Oracle出现D状态进程,何解(20250327)

来源:这里教程网 时间:2026-03-03 21:47:00 作者:

数据库管理-第306期 Oracle出现D状态进程,何解(20250327)

作者:胖头鱼的鱼缸(尹海文)
Oracle ACE Pro: Database
PostgreSQL ACE Partner
10年数据库行业经验
拥有OCM 11g/12c/19c、MySQL 8.0 OCP、Exadata、CDP等认证
墨天轮MVP,ITPUB认证专家
圈内拥有“总监”称号,非著 名社恐(社交恐怖分子)
公众号:胖头鱼的鱼缸
CSDN:胖头鱼的鱼缸(尹海文)
墨天轮:胖头鱼的鱼缸
ITPUB:yhw1809。
除授权转载并标明出处外,均为“非法”抄袭

胖头鱼的鱼缸_01.png 前天下班后接到业务方反馈,有个会话造成了相关表的其他会话读取缓慢,已经尝试KILL会话但未产生效果,会话一直标记为KILLED状态,也已经KILL对应的操作系统进程,但是进程也无法杀掉,其state为D。

1 D状态进程

这里可以用下面命令搜索D状态的进程:

ps -efl |awk '{if($2=="D")print $0}'

image.png 这里出现问题就是画红框的类似进程,而且是执行完kill session和kill -9 pid后的状态,这里说明一点截图并非为前天处理内容。 先看看进程为D状态的解释:不可中断的休眠,常见于IO上。而这个会话对应的等待则是User I/O - db file parallel read。其实这个会话确实造成了其他关联查询会话的一些等待,但并没有彻底挂死后续操作,只是变慢了,这个会话的主机信息是localhost.localdomain,无法检索到有效的主机信息。D状态进程是无法通过kill命令终止的,一般解决方案是重启操作系统,经过沟通于半夜对节点进行了重启操作,D状态进程消失。 其实在数据库中进程变为D状态是比较常见的状态,常见于进程在做磁盘和网络IO时,完成后就会释放,但是像昨晚这种完全挂死的情况是及其罕见的。

2 风云再起

昨天天早上,业务侧又反馈说,前晚重启过程中,因部分连接中断造成有部分脚本执行出现了异常,也是在数据库中kill session后发现标记KILLED后没有释放,检查进程还是内容为(LOCAL=NO)的远程连接,kill -9后变成了[oracle_pid_z],似乎昨日重现(其实就是第一节中的截图)。但是又有不同的地方,因为在数据库中的会话在大多数该操作后都消失了(进程与会话关联已经断开,D状态进程可能需要内核周期判断后才会被清理),仅有一个会话还留存,并且出现了昨天类似的等待场景。通过数据库内查询该语句的详细内容:

select sid,serial#,status,machine,program,process from v$session where sid=`sid`;

image.png 可以看到这个操作是来自于另一套Oracle数据库的dblink的操作,是脚本中的一部分,正好对端数据库也是我管,检查后发现虽然业务方把脚本停了,但是对应会话和进程还在,排查沟通后执行:

kill -9 280696

完成后源库的相关后续等待均消失,数据库相关响应恢复正常吗。这里也可以反推出,因网络IO出现的D状态进程可以通过中断网络连接来释放。这里和前晚不一样的地方是,可以通过全链路排查到源头,而之前的却不行。

3 SQL汇总

除了上面查询客户端相关信息的语句外,本次查询还涉及其他语句:

-- 查询活动会话相关信息
select a.inst_id,a.sid, serial#,a.sql_id, c.event,blocking_instance,blocking_session, a.last_call_et
  from gv$session a, gv$session_wait c
  where a.sid = c.sid   and a.status = 'ACTIVE'
  and username not in ('SYS', 'SYSTEM')
  and a.inst_id = c.inst_id
  and username is not null
  order by a.inst_id,a.last_call_et,a.sql_id,a.last_call_et;
-- 关联查询会话信息和本机进程
select s.inst_id,s.sid,s.serial#,p.spid from gv$session s,gv$process p where s.inst_id=p.inst_id and s.paddr=p.addr and s.sid=`sid`|p.spid=`pid`;

4 锦上添花

在前晚的处置中,还发现了对应语句的优化点,全语句就不放出来了,这里放一个where条件即可:

...
substr(a.back_date,1,7)=:2
...

这张表上在back_date上建立了普通索引,但是通过substr截断后是不会使用到该列索引的,应当根据业务逻辑将“反向”截断放在等号后面,或者根据使用情况建立函数索引,合理使用索引降低IO,可以尽可能的减少相关问题出现。 另一方面也要求业务方对所有服务器配置主机名,调整脚本的退出机制。

总结

D状态进程不可怕,能判断源头的就源头处理,再不济也能重启。 老规矩,知道写了些啥。

相关推荐