it编程 > 数据库 > Oracle

Oracle数据库中锁等待与会话阻塞故障排查与解决

38人参与 2026-09-08 Oracle

凌晨两点,告警群突然炸了:订单服务大面积超时,数据库 cpu 不算高,但应用线程池被打满。登录数据库一查,发现大量会话状态是 waiting,等待事件集中在 enq: tx - row lock contention。这不是性能慢,而是典型的锁等待与会话阻塞事故。本文结合真实复盘经验,梳理一套可直接落地的排查步骤,帮你在黄金时间内快速止血、定位根因。

一、先止血:快速识别“锁源”

锁问题的核心,永远是找到阻塞源头(blocker) ,而不是盲目杀会话。

1. 查看当前阻塞关系

select
    s.sid,
    s.serial#,
    s.username,
    s.status,
    s.sql_id,
    s.event,
    s.wait_class,
    s.seconds_in_wait,
    s.blocking_session,
    s.blocking_session_status
from v$session s
where s.blocking_session is not null
order by s.seconds_in_wait desc;

重点关注:

2. 定位顶层阻塞者(root blocker)

很多时候是“连环堵”,a 堵 b,b 堵 c。要找到最顶层的 a:

select
    s.sid,
    s.serial#,
    s.username,
    s.status,
    s.sql_id,
    s.event,
    s.seconds_in_wait
from v$session s
where s.sid in (
    select distinct blocking_session
    from v$session
    where blocking_session is not null
)
and s.blocking_session is null;

这个查询返回的,就是没有被人阻塞、但正在阻塞别人的会话,通常是事故源头。

3. 紧急止血:谨慎杀会话

确认是异常会话后,可临时 kill:

alter system kill session 'sid,serial#' immediate;

注意:

二、再定位:搞清楚“卡在哪”

找到阻塞会话后,下一步是确认它在做什么、锁了什么对象。

1. 查看会话正在执行的 sql

select sql_id, sql_text
from v$sql
where sql_id = '上一步拿到的sql_id';

常见场景:

2. 查看被锁的对象

select
    l.session_id,
    l.locked_mode,
    o.owner,
    o.object_name,
    o.object_type
from v$locked_object l
join dba_objects o on l.object_id = o.object_id
order by l.session_id;

locked_mode 含义速查:

3. 查看事务与回滚段

select
    t.xidusn,
    t.xidslot,
    t.xidsqn,
    t.status,
    t.start_time,
    t.used_ublk,
    s.sid,
    s.serial#,
    s.username
from v$transaction t
join v$session s on t.addr = s.taddr;

如果看到某个事务 start_time 很早、used_ublk 很大,基本可以判定是长事务惹的祸。

三、深复盘:为什么会发生

从多次生产事故中总结,oracle 锁等待的高频根因集中在以下几类:

1. 忘记提交事务(最高频)

开发人员手动在 pl/sql developer 中执行了 update,改完数据后去开会、吃饭、下班,会话一直挂着,锁迟迟不释放。

典型特征

优化建议

2. 大事务批量更新

一次性更新几十万行,且没分批提交,导致:

优化建议

3. 索引缺失导致锁升级

update t_order set status = 'paid' where order_no = 'xxx'

如果 order_no 没有唯一索引,oracle 会锁定更多行,甚至全表扫描时的锁范围会大幅放大。

优化建议

4. 并发设计不合理

多个线程同时更新同一行数据,例如秒杀场景下的库存扣减,没有使用:

导致大量会话互相等待。

优化建议

5. ddl 引发的阻塞

alter tablecreate index 等 ddl 需要表级锁,会阻塞所有 dml。

优化建议

四、标准化排查 sop(可直接照抄)

遇到锁等待告警,按以下顺序操作,通常 10 分钟内可以定位问题:

确认现象

找阻塞源

判断会话状态

定位 sql 与对象

沟通与决策

事后处理

五、防患于未然:运维侧建议

六、复盘总结模板(可直接用)

每次事故后,建议输出一份简短复盘:

故障时间:2026-08-xx 02:15 ~ 02:40

影响范围:订单服务超时,影响约 3% 请求

根因:开发人员在测试环境误连生产,执行 update 后未提交

处理动作:kill sid=1234 会话,事务回滚耗时 2 分钟

改进项

  1. 生产账号禁用 dml 权限
  2. 增加锁等待告警阈值
  3. 培训开发规范:dml 必须显式提交

到此这篇关于oracle数据库中锁等待与会话阻塞故障排查与解决的文章就介绍到这了,更多相关oracle锁等待与会话阻塞内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

Oracle包是什么?包和包体创建步骤详解

09-08

Oracle表空间管理怎么做?从原理到实操全解析

09-08

Oracle如何查询正在执行的语句、锁表、耗费资源的语句

09-08

Oracle包是什么?一文带你搞懂包的创建与使用

09-09

Oracle普通表改造分区表的方法汇总

09-06

Oracle merge into用法详解:如何同时更新插入删除数据

09-10

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论