暂无图片
暂无图片
12
暂无图片
暂无图片
暂无图片

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

原创 胖头鱼的鱼缸 2025-03-26
426

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

胖头鱼的鱼缸_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状态进程不可怕,能判断源头的就源头处理,再不济也能重启。
老规矩,知道写了些啥。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论