Oracle数据库中怎么查找锁表原因_如何用存储过程快速定位
Oracle数据库中怎么查找锁表原因
遇到数据库响应变慢,怀疑是锁表时,别急着“杀”会话。先得把问题搞清楚:到底是哪张表被锁了?谁干的?为什么?下面这套方法,能帮你快速定位到根因。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
查 v$locked_object 确认哪些表真被锁了
第一步,先确认是不是真的发生了锁表。最快的方法就是查询 v$locked_object 视图。这个视图很“实在”,它只返回当前正持有 DML 锁的对象——简单说,就是那些因为 INSERT、UPDATE、DELETE 操作没提交,导致行级锁升级或阻塞的表。

不过要注意,它不包含 SELECT FOR UPDATE 产生的轻量级锁,也不反映 DDL 锁(比如 ALTER TABLE)。所以,如果查出来是空结果,并不代表绝对安全,可能只是锁的类型不同。
一个常用的组合查询是这样的:
SELECT b.owner, b.object_name, a.session_id, a.locked_mode FROM v$locked_object a, dba_objects b WHERE a.object_id = b.object_id;
怎么解读结果呢?如果 object_name 那列出现了你关心的表名,那它大概率就是“罪魁祸首”。再看 locked_mode 这个值,如果显示为 3(Row-X,行排他锁)或 6(Exclusive,排他锁),通常就意味着有写操作没提交,锁就是这么来的。
- 执行这个查询需要
SELECT ANY DICTIONARY或SELECT_CATALOG_ROLE权限,否则会报 ORA-00942 错误。 - 关联
dba_objects要求用户有 DBA 角色或对目标 schema 有访问权限。如果权限不够,可以尝试换成all_objects,但这样可能会漏掉其他用户下的表。 - 这个视图是“实时快照”,不保留历史记录,只反映“此刻”的锁状态。一些瞬间完成并提交的事务锁,很容易被错过。
连查 v$session 和 v$sql 定位谁在跑什么 SQL
光知道是哪张表和哪个会话 ID(SID)还不够。关键是要弄清楚:这个会话在干什么?它从哪台机器连过来的?运行的是什么程序?执行的又是哪条 SQL 语句?
这就需要把 v$locked_object 里的 session_id,关联到 v$session 视图,再通过 sql_id 找到具体的 SQL 文本。下面这条查询链路兼容 Oracle 11g 到 19c,非常实用:
SELECT s.sid, s.serial#, s.username, s.machine, s.program, s.logon_time,
q.sql_text
FROM v$locked_object l
JOIN v$session s ON l.session_id = s.sid
LEFT JOIN v$sql q ON s.sql_id = q.sql_id
WHERE s.status = 'ACTIVE' OR s.sql_id IS NOT NULL;
拿到结果后,重点看 sql_text 字段。如果里面是一条长时间的 UPDATE 语句,并且一直没 COMMIT,那基本就是锁表的根源了。如果 SQL 文本显示是 BEGIN ... END; 这样的 PL/SQL 块开头,那说明锁可能来自某个存储过程的内部逻辑。
- 注意,
v$sql只缓存已经硬解析过的 SQL。如果语句刚执行完就被刷出了共享池,这里的sql_text可能会是空的。这时候可以尝试查询q.sql_fulltext(需要 12c 及以上版本),或者通过v$session的prev_sql_addr去关联v$sqlarea。 machine和program这两个字段能帮你快速判断源头:是来自某台应用服务器、PL/SQL Developer 这样的客户端工具,还是数据库自身的某个定时任务进程。- 如果
username显示为NULL,那可能是后台进程(比如 job queue sla ve)在持锁,处理时需要格外小心。
用存储过程批量查锁并生成 kill 语句(不自动执行)
手动拼接 ALTER SYSTEM KILL SESSION 'sid,serial#' 这样的命令既繁琐又容易出错。一个更安全高效的折中方案是:让存储过程帮你生成所有需要执行的 KILL 命令,但先不自动执行。这样你可以在执行前,最后人工核对一遍。
下面这个查询就是一个“命令生成器”。它只输出 KILL 语句的列表,把决定权留给你:
SELECT 'ALTER SYSTEM KILL SESSION ''' || s.sid || ',' || s.serial# || ''' IMMEDIATE;' AS kill_cmd,
s.username, s.machine, o.object_name, s.logon_time
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 IN ('YOUR_TABLE_NAME');
使用时,只需要把 YOUR_TABLE_NAME 换成真实的表名。运行后,你会得到一串带注释的 KILL 命令。复制粘贴前,务必扫一眼 username 和 machine,确认要终止的会话是否合理。
- 语句中加上
IMMEDIATE是为了绕过正常的等待队列,立刻中断会话,避免KILL SESSION命令自身也被阻塞。 - 如果目标表被多个 SID 锁定,结果会返回多行,记得不要漏掉任何一行。
- 这条语句本身只做查询,不修改任何数据,没有权限风险,普通开发账号只要能查询字典视图就能运行。
为什么不能只依赖 v$lock 查锁表原因
很多朋友会想到去查 v$lock 视图,因为它看起来更“底层”。但这个视图展示的是所有类型的锁(包括 TX、TM、UL、DX 等),信息比较庞杂。其中,只有 TM(DML enqueues)才对应表级的锁行为,而 TX 只是事务锁,并不指向具体的数据库对象。
新手常犯的一个错误是,在 v$lock 里看到一堆 TX 类型的锁,就以为是“锁表”了。其实那很可能只是两个会话在争用同一个回滚段,和具体的表没有直接关系。
下面就是一个典型的、容易产生误导的查询:
SELECT sid, type, id1, id2, lmode FROM v$lock WHERE type = 'TX';
这种查询结果里的 id1 和 id2 分别是回滚段编号和槽位号,根本看不出是哪张表被锁。真想准确定位,还是得走 v$locked_object → v$session → v$sql 这条路径。
- 在
v$lock中,只有type = 'TM'的记录才值得仔细看,这时id1就是 object_id,可以关联到dba_objects找到具体的表。 - DBA 有时会用
DBA_BLOCKERS和DBA_WAITERS来查死锁,但这两个视图只在发生真正的死锁(抛出 ORA-00060 错误)时才有记录,平时是空的。 - Oracle 12c 之后引入了
v$session_blockers,比老视图更实时,但依然不如v$locked_object来得直观和精准。
查v$locked_object可快速确认哪些表正被 DML 锁持有,它只反映当前真实锁表状态,需结合dba_objects和v$session定位会话及 SQL,locked_mode为 3 或 6 表明存在未提交的写操作,是锁表主因。
最后,还有一个最容易被忽略的点:锁可能并不直接发生在表本身,而是发生在它的索引、约束触发器或物化视图日志上。如果你在 v$locked_object 里没看到目标表,可以尝试去查它的索引名(通过 dba_indexes)、主键约束名(通过 dba_constraints)。或者,执行 SELECT * FROM v$access WHERE object = 'YOUR_PROC_NAME',看看是不是某个存储过程正在被其他会话调用而持有了锁。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
MySQL报错Unknown column in field list_检查SQL字段名拼写
MySQL报错“Unknown column xxx in field list ”的深度解析与实战排查 遇到“Unknown column ‘xxx’ in ‘field list’”这个报错,很多人的第一反应是检查拼写。这没错,但事情往往没那么简单。这个错误的本质,是MySQL在解析你的S
mysql如何查询字段值为空字符串的记录_空值与空串的区别判断
查空字符串应使用 WHERE column_name = ,但该条件无法匹配 NULL;需同时用 IS NULL 或 IFNULL() 处理,且 CASE 判断中 IS NULL 必须优先于 = 。 直接用 = 查空字符串,但别误判 NULL 想找出字段值为空字符串的记录,最直接的写法
mysql如何判断字段是否满足邮箱正则格式_REGEXP复杂匹配
不推荐用 MySQL 原生 REGEXP 做严格邮箱校验,因其正则引擎功能有限、不支持关键特性且无法覆盖 RFC 5322 复杂规则,仅适合粗筛明显非法值,严格校验应交由应用层完成。 MySQL 用 REGEXP 判断邮箱格式是否可靠? 开门见山,先说核心结论:不推荐依赖 MySQL 原生的 REG
Oracle RAC如何处理脑裂(Split-Brain)?配置冗余私网心跳
Oracle RAC如何真正预防脑裂?三重心跳与多数派原则是关键 一个常见的误解是,为Oracle RAC增加一块私联网卡就能高枕无忧地防止脑裂。事实并非如此。RAC本身并不“处理”已经发生的脑裂,而是通过一套精密的三重心跳机制、Quorum(法定人数)算法和IO Fencing(I O隔离)来主动
mysql读写分离配置_MyISAM与InnoDB在主从环境表现
MyISAM 与 InnoDB 在主从环境表现 MyISAM 表在 MySQL 主从复制中不可靠,因不支持事务导致 binlog 与表更新非原子,易丢数据;InnoDB 凭借 crash-safe 和 XID 关联机制保障复制一致性,是唯一稳妥选择。 MyISAM 表在 MySQL 主从复制中会丢数
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

