数据库管理306期 2025-03-27
数据库管理-第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。 除授权转载并标明出处外,均为“非法”抄袭

前天下班后接到业务方反馈,有个会话造成了相关表的其他会话读取缓慢,已经尝试KILL会话但未产生效果,会话一直标记为KILLED状态,也已经KILL对应的操作系统进程,但是进程也无法杀掉,其state为D。
1 D状态进程
这里可以用下面命令搜索D状态的进程:
ps -efl |awk '{if($2=="D")print $0}'

这里出现问题就是画红框的类似进程,而且是执行完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`;

可以看到这个操作是来自于另一套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状态进程不可怕,能判断源头的就源头处理,再不济也能重启。
老规矩,知道写了些啥。




