应查询v$locked_object关联dba_objects、dba_tables和v$session,而非仅查v$lock;它精准定位活动段级TM锁对应的表、表空间及会话,并自动过滤伪锁与无效对象。

怎么快速定位正在阻塞DML的段级锁
Oracle里“段锁”不是独立锁类型,而是指 TM(表级DML锁)作用在某个具体段(segment)上,比如一张表或一个分区。真正造成DML阻塞的,往往是某会话持有了该段的排他 TM 锁但未提交,导致其他会话对同一段执行 INSERT/UPDATE/DELETE/SELECT ... FOR UPDATE 时被挂起。
别查 V$LOCK WHERE TYPE = 'TM' —— 它只返回 SID 和 ID1(即 OBJECT_ID),不告诉你这个锁落在哪个表空间、哪张表、甚至是不是有效活动锁。
应该用这个组合查询:
SELECT l.session_id, s.serial#, s.username, s.osuser, s.machine,
o.object_name, o.object_type, t.tablespace_name,
l.locked_mode, s.status, s.sql_id
FROM v$locked_object l
JOIN dba_objects o ON l.object_id = o.object_id
JOIN dba_tables t ON o.object_name = t.table_name AND o.owner = t.owner
JOIN v$session s ON l.session_id = s.sid
WHERE o.object_type IN ('TABLE', 'TABLE PARTITION');
关键点:
-
dba_tables.tablespace_name能直接看到锁影响的表空间,避免误判(比如业务查USERS,实际锁在INDEX_TBS) - 过滤
object_type是为了排除索引、LOB等非主数据段干扰 - 带上
s.sql_id后续可关联v$sql查原始语句
为什么 V$LOCKED_OBJECT 比 V$LOCK 更可靠
V$LOCKED_OBJECT 是经过过滤的视图:它只包含当前持有锁且被其他会话等待的活动对象锁,已自动剔除已释放、空闲或仅用于一致性读的伪锁。而 V$LOCK 会返回大量瞬时、非阻塞型锁(如事务刚启动还没碰数据时的空 TX 锁),噪音极大。
常见误判场景:
- 查到
V$LOCK里有多个TM锁,但实际只有一个是block = 1的源头 - 锁对应的
OBJECT_ID在dba_objects中查不到(已被 DROP 或是临时段) - 会话状态是
INACTIVE,但锁还在 —— 很可能是个“孤儿事务”,得结合s.last_call_et判断是否僵死
如何确认阻塞链和源头SQL
光知道谁持锁不够,得搞清谁在等、等了多久、等的是什么资源。用下面这个带阻塞关系的查询:
SELECT blocking_session,
sid, serial#, username,
event, seconds_in_wait,
sql_id, prev_sql_id
FROM v$session
WHERE blocking_session IS NOT NULL OR blocking_session_status = 'VALID';
再配合查源头SQL:
SELECT sql_text FROM v$sql WHERE sql_id IN ( SELECT sql_id FROM v$session WHERE sid = &blocking_sid );
注意几个坑:
-
sql_id可能为空(比如会话在解析、网络等待、或用了绑定变量但没缓存执行计划),此时看prev_sql_id - 如果
sql_text显示为NULL,说明语句已老化出共享池,需查v$sqlarea或启用 SQL Trace - 某些 JDBC 应用会把多条语句拼成一个长字符串,
sql_text只显示开头几十字,得结合program和machine定位应用端逻辑
杀会话前必须检查的三件事
执行 ALTER SYSTEM KILL SESSION 'sid,serial#' 前,务必确认:
- 该会话是否属于关键批处理或ETL任务(查
s.program和s.module,比如oracle@prod01 (J001)很可能是 Data Pump) - 锁是否由未提交的
UPDATE引起(查s.taddr是否非空,非空表示事务仍在进行中;若为空,可能是会话异常断开但事务未回滚) - 是否存在跨实例锁(RAC 环境下,
inst_id字段必须和当前实例一致,否则KILL SESSION不生效)
最常被忽略的是:被杀会话的事务不会立即回滚,而是进入“回滚段清理”阶段,期间仍可能短暂持有锁。如果等不及,只能找 DBA 手动触发 ROLLBACK 或重启实例(极端情况)。


















