
好的,我们来对 Oracle 19c 数据库中的 V$SESSION_WAIT_HISTORY 动态性能视图进行最全面、最深入的解析。
V$SESSION_WAIT_HISTORY 是一个极其有价值的性能诊断视图,它提供了每个活动会话最近发生的多次等待事件的详细历史记录。与 V$SESSION_WAIT(只显示当前或最后一次等待)和 V$SESSION_EVENT(只显示累计值)不同,它让你能够像“回放录像”一样,查看会话刚刚经历过什么,这对于诊断短暂的、间歇性的性能问题至关重要。
一、字段含义详解
| 字段名 | 数据类型 | 描述 | 重要说明与示例 |
|---|---|---|---|
| SID | NUMBER | 产生等待事件的会话标识符 (Session Identifier)。 | 与 V$SESSION.SID 对应。 |
| SEQ# | NUMBER | 等待序列号。在一个会话内,每次等待都会分配一个唯一的、递增的序列号。 | 用于判断等待事件发生的先后顺序。序列号越大,事件发生的时间越近。 |
| EVENT | VARCHAR2(64) | 等待事件的名称。 | 例如:'db file sequential read', 'enq: TX - row lock contention', 'latch: shared pool' |
| P1TEXT | VARCHAR2(64) | 等待事件第一个附加参数的文本描述。 | 例如:'file#' |
| P1 | NUMBER | 等待事件第一个附加参数的具体数值。 | 其含义由 EVENT 决定。例如,对于 'db file sequential read',P1 代表文件号 (file_id)。 |
| P2TEXT | VARCHAR2(64) | 等待事件第二个附加参数的文本描述。 | 例如:'block#' |
| P2 | NUMBER | 等待事件第二个附加参数的具体数值。 | 对于 'db file sequential read',P2 代表起始块号 (block_id)。 |
| P3TEXT | VARCHAR2(64) | 等待事件第三个附加参数的文本描述。 | 例如:'blocks' |
| P3 | NUMBER | 等待事件第三个附加参数的具体数值。 | 对于 'db file sequential read',P3 代表要读取的块数。 |
| WAIT_TIME | NUMBER | 此次等待的实际持续时间(单位:百分之一秒,即 10ms)。 | > 0: 实际的等待时间。 0: 等待时间极短,无法计量。 -1: 时间统计未开启 ( TIMED_STATISTICS=false)。-2: 参数已废弃。 |
| WAIT_COUNT | NUMBER | 该等待事件发生的次数。注意:此视图中的 WAIT_COUNT 指的是该特定事件序列(由 SID, EVENT, P1, P2, P3 确定)在历史记录中出现的次数,并非会话累计值。 | 用于判断一个相同的等待是否在短时间内反复发生。 |
二、核心原理与底层机制
1. 数据来源与底层基表
V$SESSION_WAIT_HISTORY 是一个动态性能视图,其数据来源于 SGA 中的一个内存循环缓冲区。这个缓冲区为每个活动会话预留了一小块空间(通常可存储最近 10 次等待事件的信息)。
其底层源是 X$ 表,通常是像 X$KSWHST 这样的底层结构。这些 X$ 表直接映射了 SGA 中用于存储会话等待历史的内存区域。DBA 无需直接查询 X$ 表,V$SESSION_WAIT_HISTORY 提供了更友好、稳定的接口。
2. 详细工作机理
- 会话初始化:当一个会话变为活动状态时,Oracle 在 SGA 中为其分配一个小的、固定大小的缓冲区(如 10 个槽位)来记录等待历史。
- 等待事件发生:每当会话完成一个非空闲等待事件(Non-idle wait event)时:
- Oracle 内核将该事件的详细信息(
EVENT,P1,P2,P3,WAIT_TIME等)写入为该会话分配的缓冲区的下一个槽位。 - 如果缓冲区已满(例如已存满10次等待),则新的记录会覆盖最旧的那条记录(FIFO,先进先出)。因此,这个视图永远只保存最近的 N 次等待。
SEQ#会递增,WAIT_COUNT会对完全相同的等待事件进行计数。
- Oracle 内核将该事件的详细信息(
- 数据查询:当你查询
V$SESSION_WAIT_HISTORY时,Oracle 实际上是直接从这个 SGA 的内存缓冲区中读取数据,因此它的速度非常快,并且显示的是近乎实时的信息。 - 会话断开:当会话断开连接后,其对应的等待历史缓冲区被释放,该会话的记录将从视图中消失。
3. 与 ASH (Active Session History) 的关系
V$SESSION_WAIT_HISTORY 和 V$ACTIVE_SESSION_HISTORY (ASH) 功能上有相似之处,但侧重点不同:
V$SESSION_WAIT_HISTORY:- 深度:提供每个会话最近最多10次等待的非常详细的信息(包括精确的 P1/P2/P3 参数)。
- 广度:仅覆盖极短的时间窗口(仅最后几次等待)。
- 开销:几乎无额外开销,是内核等待机制的自然副产品。
V$ACTIVE_SESSION_HISTORY:- 深度:每秒采样一次,只记录会话在采样点时是否在等待以及等待什么事件,不包含每次等待的精确时长和详细参数(但包含 SQL_ID, 对象号等更多会话上下文)。
- 广度:默认在内存中保存约1小时的数据,提供更长的历史视角。
- 开销:有轻微的采样开销。
总结:V$SESSION_WAIT_HISTORY 用于微观分析,查看会话刚刚发生的具体等待细节;ASH 用于宏观分析,回溯一段时间内的性能问题。两者可结合使用。
三、常用查询 SQL 示例
-
查看某个会话(SID=135)最近的等待历史
SELECT sid, seq#, event, p1text, p1, p2text, p2, p3text, p3, wait_time, wait_count FROM v$session_wait_history WHERE sid = 135 ORDER BY seq# DESC; -- 最新的等待排在前面 -
诊断特定的短暂等待:查找所有经历过 ‘enq: TX - row lock contention’ 的会话及其历史
SELECT swh.sid, s.username, s.osuser, s.program, s.sql_id, swh.seq#, swh.event, swh.p1, swh.p2, swh.p3, -- 这些参数对解码锁信息至关重要 swh.wait_time, swh.wait_count FROM v$session_wait_history swh JOIN v$session s ON swh.sid = s.sid WHERE swh.event = 'enq: TX - row lock contention' ORDER BY swh.sid, swh.seq# DESC; -
结合参数解读:将等待事件与具体对象关联(例如,查找I/O等待对应的对象)
SELECT swh.sid, swh.seq#, swh.event, swh.p1 AS file_id, swh.p2 AS block_id, DO.owner, DO.object_name, DO.object_type FROM v$session_wait_history swh LEFT JOIN dba_objects DO ON ( DO.data_object_id = ( SELECT data_object_id FROM dba_extents WHERE file_id = swh.p1 AND swh.p2 BETWEEN block_id AND block_id + blocks - 1 AND ROWNUM = 1 ) ) WHERE swh.event IN ('db file sequential read', 'db file scattered read') AND swh.wait_time > 5 -- 只查等待时间较长的 ORDER BY swh.wait_time DESC;注意:此查询对性能有一定影响,请在必要时使用。
-
查找重复出现的短等待(高频率等待)
SELECT sid, event, p1, p2, p3, wait_count, wait_time FROM v$session_wait_history WHERE wait_count > 3 -- 相同的等待短时间内发生了多次 ORDER BY wait_count DESC;
四、主要应用场景
-
诊断间歇性阻塞或挂起:
用户报告“应用偶尔会卡一下,但马上又好了”。DBA 可以在问题发生后立即连接到数据库,查询相关会话的V$SESSION_WAIT_HISTORY,查看其在“卡顿”期间到底经历了什么等待(例如,一个短暂的行锁等待或一个缓慢的I/O),即使该等待现在已结束。 -
分析具体的等待事件参数:
当V$SESSION或AWR报告显示系统存在大量的buffer busy waits时,你可以使用此视图找到最近发生这种等待的会话,并通过P1(file#),P2(block#) 参数精确定位到热点块,进而分析原因。 -
验证问题是否解决:
在实施了一个优化措施(如调整SQL、扩容等)后,可以持续监控相关会话的等待历史,观察之前频繁出现的、导致性能问题的等待事件是否已经消失或等待时间大幅缩短。 -
关联分析:
将一个会话的等待历史与其当前执行的 SQL (V$SESSION.SQL_ID)、会话程序信息等结合,可以建立从“应用请求”到“数据库资源等待”的完整证据链。
五、相关视图
V$SESSION:提供会话的基本状态和信息(如USERNAME,STATUS,SQL_ID),是关联分析的起点。V$SESSION_WAIT:显示会话当前或最后一次的等待信息。V$SESSION_WAIT_HISTORY是其历史的扩展。V$ACTIVE_SESSION_HISTORY(ASH):提供所有活动会话的历史采样信息,时间范围更广,但细节深度不如V$SESSION_WAIT_HISTORY。DBA_EXTENTS/DBA_OBJECTS:用于将P1(file#) 和P2(block#) 参数解析为具体的表、索引等对象名称。V$EVENT_NAME:提供等待事件的元数据,包括参数的含义(PARAMETER1,PARAMETER2,PARAMETER3)。
总结:V$SESSION_WAIT_HISTORY 是 Oracle DBA 武器库中一把精准的“手术刀”,它提供了其他视图无法提供的、极细时间粒度下的会话等待细节,是解决棘手性能问题的利器。其核心价值在于能够回溯刚刚发生但已结束的等待事件。
欢迎关注我的公众号《IT小Chen》
1104

被折叠的 条评论
为什么被折叠?



