【Oracle】Oracle诊断系列(2/6):锁问题与阻塞分析——解决“卡住”的会话

🔗 接上一篇《Oracle健康体检指南》,今天我们深入数据库的"交通系统"------锁机制,解决会话阻塞和死锁问题。

你是否遇到过:

  • 操作突然卡住,无响应?
  • 应用提示"资源忙"?
  • 某些事务长时间不提交?

这些问题,很可能是因为锁等待。Oracle的锁机制保证了数据一致性,但不当的使用会导致性能瓶颈。今天,我就教你如何快速定位和解决锁问题。


🧠 锁机制基础

Oracle主要锁类型:

  • TX锁:事务锁(行级锁)
  • TM锁:表级锁
  • DDL锁:数据定义语言锁

⚠️ 关键概念:

  • 阻塞:会话A持有锁,会话B等待
  • 死锁:A等B,B等A → Oracle自动检测并终止一个会话

1️⃣ 实时会话监控

复制代码
-- 查看所有非后台会话
SELECT
    s.sid,
    s.serial#,
    s.username,
    s.status,
    s.osuser,
    s.machine,
    s.program,
    s.module,
    s.action,
    s.client_info,
    s.logon_time,
    ROUND(s.last_call_et / 60, 2) AS last_call_min,
    s.state AS wait_state,
    s.event,
    s.wait_class,
    s.seconds_in_wait,
    s.sql_id,
    s.prev_sql_id,
    s.row_wait_obj# AS row_wait_object_id,
    s.row_wait_file# AS row_wait_file,
    s.row_wait_block# AS row_wait_block,
    s.blocking_session_status,
    s.blocking_instance,
    s.blocking_session,
    s.paddr
FROM
    v$session s
WHERE
    type != 'BACKGROUND';

✅ 关键字段解读:

  • blocking_session:被谁阻塞
  • event:当前等待事件
  • seconds_in_wait:等待时长
  • row_wait_*:等待的具体行位置

2️⃣ 锁阻塞链分析

复制代码
-- 锁阻塞关系树
WITH blocking_tree AS (
    SELECT 
        'alter system kill session ''' || s.sid || ',' || s.serial# || ',@' || s.inst_id || ''' immediate;' AS kill_command,
        SYS_CONNECT_BY_PATH(s.sid || '@' || s.inst_id, ' ← ') AS blocking_path,
        s.inst_id,
        s.sid,
        s.serial#,
        s.username,
        s.osuser,
        s.machine,
        s.program,
        s.status,
        s.sql_id,
        s.event,
        s.blocking_session,
        s.blocking_instance,
        CONNECT_BY_ISLEAF AS is_blocked_end,
        LEVEL AS blocking_level,
        CASE WHEN lo.xidusn IS NOT NULL THEN 'YES' ELSE 'NO' END AS holds_locked_object
    FROM 
        gv$session s
        LEFT JOIN gv$locked_object lo ON s.sid = lo.session_id AND s.inst_id = lo.inst_id
    WHERE 
        s.blocking_session IS NOT NULL  
    CONNECT BY 
        (s.sid || '@' || s.inst_id) = PRIOR (s.blocking_session || '@' || s.blocking_instance)
    START WITH 
        s.blocking_session IS NOT NULL
),
sql_texts AS (
    SELECT DISTINCT sql_id, sql_text 
    FROM gv$sql 
    WHERE sql_id IN (SELECT sql_id FROM blocking_tree WHERE sql_id IS NOT NULL)
)
SELECT 
    bt.kill_command,
    bt.blocking_path,
    bt.inst_id,
    bt.sid,
    bt.serial#,
    bt.username,
    bt.osuser,
    bt.machine,
    bt.program,
    bt.status,
    bt.event,
    bt.blocking_level,
    bt.holds_locked_object,
    st.sql_text
FROM 
    blocking_tree bt
    LEFT JOIN sql_texts st ON bt.sql_id = st.sql_id
ORDER BY 
    bt.blocking_level DESC, bt.sid;

✅ 解读:

  • blocking_path:显示阻塞链(被谁阻塞)
  • kill_command:终止会话的命令
  • holds_locked_object:是否持有锁对象

3️⃣ 锁定对象查询

复制代码
-- 被锁定的对象
SELECT 
    do.object_name,
    lo.session_id,
    lo.inst_id,
    lo.oracle_username,
    lo.os_user_name,
    lo.process,
    lo.locked_mode
FROM 
    gv$locked_object lo
    JOIN dba_objects do ON lo.object_id = do.object_id
ORDER BY 
    lo.inst_id, lo.session_id;

✅ 锁定模式:

  • 1:NULL
  • 2:行共享(RS)
  • 3:行排他(RX)
  • 4:共享(S)
  • 5:S/Row-X
  • 6:排他(X)
    🔍 重点关注:locked_mode = 6(排他锁)

4️⃣ 长时间事务检测

复制代码
-- 运行超过5分钟的事务
SELECT 
    s.inst_id,
    s.sid,
    s.serial#,
    s.username,
    s.status,
    s.machine,
    s.program,
    t.start_time,
    ROUND(SYSDATE - t.start_time, 2) * 24 * 60 AS duration_minutes,
    s.sql_id,
    sq.sql_text
FROM 
    gv$transaction t
    JOIN gv$session s ON t.addr = s.taddr
    LEFT JOIN gv$sql sq ON s.sql_id = sq.sql_id AND sq.inst_id = s.inst_id
WHERE 
    (SYSDATE - t.start_time) > INTERVAL '5' MINUTE 
ORDER BY 
    duration_minutes DESC;

🚨 风险:

  • 长时间事务会:
    • 持有锁不释放
    • 阻塞其他会话
    • 增加UNDO空间使用

✅ 锁问题处理策略

场景 处理方案
普通阻塞 等待或联系用户提交/回滚
关键业务阻塞 使用 kill_command 终止会话
死锁 Oracle自动处理
长时间事务 联系应用负责人

⚠️ 终止会话警告:

复制代码
ALTER SYSTEM KILL SESSION 'sid,serial#,@inst_id' IMMEDIATE;
  • 会回滚未提交的事务
  • 可能影响应用一致性

📣 总结

锁问题诊断四步法:

  1. 🕵️‍♂️ 用 v$session 发现阻塞会话
  2. 🔗 用阻塞链分析阻塞关系
  3. 🔍 查询被锁定的对象
  4. ⏱️ 检测长时间运行的事务

🔗 下期预告:

下一篇《Oracle性能瓶颈定位》,我们将通过AWR报告和SQL监控,定位慢查询和性能热点。

📌 点赞 + 收藏,告别会话阻塞!

👉 让你的数据库畅通无阻!

相关推荐
cqsztech4 小时前
Oracle 26ai 2节点RAC 保姆级搭建步骤
数据库·oracle
TDengine (老段)4 小时前
金融风控系统中的实时数据库技术实践
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
看我干嘛!4 小时前
第三次python作业
服务器·数据库·python
2501_936960364 小时前
ROS快速入门教程
数据库·mongodb
知识分享小能手4 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle 的闪回技术 — 语法知识点与使用方法详解(19)
数据库·学习·oracle
踢足球09294 小时前
寒假打卡:2026-01-31
数据库·sql
是小崔啊4 小时前
PostgreSQL快速入门
数据库·postgresql
xxxmine4 小时前
Redis 持久化详解:RDB、AOF 与混合模式
数据库·redis·缓存
yufuu984 小时前
使用Scikit-learn进行机器学习模型评估
jvm·数据库·python