查v$locked_object需联查dba_objects和v$session才能定位锁表源头,如执行select s.sid,s.serial#,s.username,s.machine,s.program,o.object_name,l.locked_mode from v$locked_object l join dba_objects o on l.object_id=o.object_id join v$session s on l.session_id=s.sid where o.object_name='business_data'。

查 v$locked_object + dba_objects 联合定位表锁源头
直接查 v$locked_object 只能拿到 session_id 和 object_id,但看不到表名和用户信息。必须连查 dba_objects 和 v$session 才能一次性看到「谁、在哪台机器、用什么程序、锁了哪张表、锁了多久」。
执行以下语句(注意:表名需大写,且当前用户要有 SELECT 权限):
SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, s.logon_time,
o.owner, o.object_name, l.locked_mode
FROM v$locked_object l
JOIN dba_objects o ON l.object_id = o.object_id
JOIN v$session s ON l.session_id = s.sid
WHERE o.object_name = 'BUSINESS_DATA';
-
logon_time偏早的会话,大概率是长时间未提交的“僵尸事务” -
program是sqlplus@host或JDBC Thin Client,说明来自人工或应用直连;若是oracle@host,可能是后台 job -
locked_mode = 6表示排他锁(X lock),通常由未提交的UPDATE/DELETE引起;= 3是行独占(RX),常见于SELECT ... FOR UPDATE
ORA-00054 报错时怎么反向找锁源
当执行 UPDATE 或 ALTER TABLE 突然报 ORA-00054: resource busy,说明你正被另一个会话阻塞。此时不能只查「谁锁了表」,得查「谁在等谁」。
运行这个阻塞链查询:
SELECT blocking_session, sid, serial#, username, event, sql_id FROM v$session WHERE blocking_session IS NOT NULL;
- 返回结果中
blocking_session列的值,就是真正持有锁的会话 SID - 再用该 SID 去查
v$session,就能拿到对应machine、program、sql_id - 如果
event是enq: TX - row lock contention,基本可断定是 DML 未提交;如果是enq: TM - contention,则可能是 DDL(如加索引)卡住
kill session 前必须确认的三件事
别一看到 SID 就 ALTER SYSTEM KILL SESSION。Oracle 的 kill 不是立刻生效,尤其对正在做事务回滚的会话,强行 IMMEDIATE 可能导致回滚中断、UNDO 损坏。
- 先看
v$session.status:若为INACTIVE且last_call_et > 3600(1小时),大概率可安全 kill - 查
v$transaction.start_time和used_ublk:如果事务已运行数小时、且used_ublk很大,kill 后回滚可能耗时几十分钟 - 检查
v$session.sql_id对应的 SQL:用SELECT sql_text FROM v$sql WHERE sql_id = 'xxx'确认是不是关键业务语句(比如财务结算)
为什么 DBA_LOCK.REQUEST 不适合日常排查
有些文档推荐用 DBMS_LOCK.REQUEST 尝试加锁来判断表是否被锁,这在实际运维中几乎不用——它本身就会触发一次排他尝试,可能加剧阻塞,且无法告诉你「谁锁的」。
- 该函数返回
0表示成功获取锁,1表示超时失败,4表示已被锁定,但不返回持有者信息 - 需要额外授权
EXECUTE ON DBMS_LOCK,多数生产库默认不开放 - 对分区表、IOT 表等对象行为不稳定,容易误判
真要快速验证某张表是否“可用”,直接 SELECT COUNT(*) FROM table_name WHERE ROWNUM = 1 更轻量、更安全。锁的本质是阻塞 DML/DDL,而简单 SELECT(不带 FOR UPDATE)不会申请 TM 锁。











