ORA-04021错误本质是DDL操作(如TRUNCATE、CREATE OR REPLACE、GRANT)在5分钟内无法获取对象DDL锁,需查dba_ddl_locks定位阻塞会话,结合v$session、v$locked_object和等待事件精准判断是否可安全kill。
ora-04021 不是表被“锁住”了,而是你当前操作(如 truncate、create or replace procedure、grant)无法在 5 分钟内获得对象的 ddl 锁,必须主动清理阻塞源才能继续。
查哪个会话在锁对象(v$ddl_locks 和 v$session 联查)
DDL 操作失败时,优先查 dba_ddl_locks ——它直接记录哪些会话正在持有目标对象的 DDL 锁:
SELECT session_id, owner, name, type FROM dba_ddl_locks WHERE name = 'YOUR_OBJECT_NAME';- 拿到
session_id后,立刻查v$session获取完整信息:SELECT sid, serial#, username, status, program, sql_id FROM v$session WHERE sid = <session_id>; - 注意:如果
status是INACTIVE但sql_id非空,说明该会话刚执行完语句还没释放锁,仍需 kill
杀会话前先确认是否真在占用(避免误杀长事务)
有些会话看似“卡住”,实际是正常运行的长查询(比如 SELECT COUNT(*)),直接 kill 可能导致业务中断。建议补查以下两处:
- 查
v$locked_object是否有该对象 ID 的记录:SELECT object_name, session_id FROM v$locked_object l, dba_objects o WHERE l.object_id = o.object_id AND o.object_name = 'YOUR_OBJECT_NAME'; - 查
v$session的等待事件:SELECT sid, event, state, seconds_in_wait FROM v$session WHERE sid = <target_sid>;—— 若event是library cache lock或enq: TM - contention,基本可确认是 DDL 阻塞源
kill session 失败时怎么办(ORA-00031 / 进程残留)
执行 ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE; 后若报 ORA-00031: session marked for kill,说明 Oracle 已标记但 OS 进程未退出:
- 查已标记为 KILLED 的进程:
SELECT p.spid, s.sid, s.serial#, s.username FROM v$process p, v$session s WHERE p.addr = s.paddr AND s.status = 'KILLED'; - 在数据库服务器上用操作系统命令干掉:
kill -9 <spid>(Linux)或orakill <ORACLE_SID> <spid>(Windows) - 特别注意:RAC 环境下要确认
spid所在节点,别在错误节点上执行 kill
备库/ADG 场景下容易忽略的隐藏原因
在 Active Data Guard 备库上遇到 ORA-04021,往往不是用户会话导致,而是 LGWR 或 MRP 进程被阻塞。此时常规 kill session 无效:
- 检查是否触发了已知 Bug(如
Bug 20413540),表现为 LGWR 被 USER 进程长时间阻塞 - 临时缓解方案:
ALTER SYSTEM SET "_adg_parselock_timeout" = 550 SCOPE=BOTH;(单位是厘秒,即 5.5 秒) - 该参数需在所有 ADG 实例上设置,并重启实例才生效;不建议长期开启,仅用于应急
真正难处理的从来不是怎么 kill,而是判断“该不该 kill”——一个 SELECT 卡了 20 分钟,到底是慢查询、死锁,还是远程 LOB 查询引发的 ORA-22992 副作用?查锁之前,先看 SQL 文本和等待事件,比盲目 kill 更省时间。


















