V$Session_wait or V$Session 总结

本文详细解析了Oracle数据库中V$Session_Wait视图的用途与字段含义,帮助理解会话等待状态及参数,揭示了常见误解并提供准确解读。

The view V$Session_wait can show useful information about what a session is waiting for.
Multiple selects from this view can indicate if a session is moving or not.
When wait_time=0 the session is waiting , any other value indicates CPU activity.


v$session_wait is often misinterpreted.

Often people will assume we are waiting because see an event and seconds_in_wait is rising. It should be remembered that seconds_in_wait only applies to a current wait if wait_time =0 , otherwise it is actually "seconds since the last wait completed".

 

The other column of use to clear up the misinterpretation is state which will be WAITING if we are waiting and WAITED% if we are no longer waiting.

 

Each wait event has up to 3 additional parameters giving more information about the wait. Pn TEXT tells you what Pn represents.

 

P1RAW , P2RAW , and P3RAW display the same values as the P1 , P2 , and P3 columns, except that the numbers are displayed in hexadecimal.

 

The WAIT_TIME column contains a value of -2 on platforms that do not support a fast timing mechanism when <<Parameter:TIMED_STATISTICS>> is set to FALSE . Set it to TRUE to get meaningful figures.

WAIT_TIME=-2是因为将 Parameter:TIMED_STATISTICS设置为FALSE

 

The WAIT_TIME column should only be 0 if the session is currently waiting for EVENT .

However, due to Bug:2117360 a value of "0" may show in Oracle9i when a session has actually finished waiting.

Use the value of the STATE column to check that the session is actually "WAITING " as this column shows the correct state.


 

 

Column Vers Datatype Description
SID  NUMBER Session identifier.
Join to <<View:V$SESSION>> . SID
SEQ#   NUMBER Sequence number that uniquely identifies this wait. Incremented for each wait.
EVENT   VARCHAR2(64) Resource or event for which the session is waiting.
P1TEXT   VARCHAR2 Description of first wait-event parameter (P1)
P1   NUMBER First wait-event parameter in decimal
P1RAW   RAW(4 | 8) First wait-event parameter in hexadecimal .
Column size depends on platform . 32bit = RAW(4), 64bit=RAW(8)
P2TEXT   VARCHAR2 Description of second parameter
P2   NUMBER Second parameter in decimal
P2RAW   RAW(4 | 8) Second parameter in hexadecimal
P3TEXT   VARCHAR2 Description of third parameter
P3   NUMBER Third additional parameter in decimal
P3RAW   RAW(4 | 8) Third additional parameter in hexadecimal
WAIT_TIME   NUMBER A nonzero value is the session's last wait time. A zero value means the session is currently waiting (except in Oracle 9.0 where Bug:2117360 occurs).
  • 0 - the session is currently waiting
  • -2 - duration of last wait is unknown
  • -1 - last wait was <1/100th of a second in duration
  • >0 - duration of last wait in 1/100th second units (10mS)
  • <-2 - The internal time has probably wrapped
SECONDS_IN_WAIT 7.3+ NUMBER When WAIT_TIME = 0 then this shows the number of seconds spent in the current wait (3 second granularity on most platforms / versions).
This value should NOT reset on events with timeouts.
Eg: The "enqueue" waitevent times out and re-waits (SEQ# increments) but SECONDS_IN_WAIT shows the cumulative time in wait.
Unfortunately this column does get reset in versions 9201-9203 inclusive due to Bug:2803772 .

When WAIT_TIME != 0 this column shows the number of seconds since the start of the last wait.
STATE 7.3+ VARCHAR2 Wait state:
  • WAITING (the session is currently waiting)
  • WAITED UNKNOWN TIME (duration of last wait is unknown)
  • WAITED SHORT TIME (last wait <1/100th of a second)
  • WAITED KNOWN TIME (WAIT_TIME = duration of last wait)

     

WAIT_TIME_MICRO 11.1+ NUMBER A nonzero value is the session's last wait time in microseconds, giving more precision than WAIT_TIME which is in 1/100th seconds
<think>我们遇到了一个错误:dba_objects 表或视图不存在。这是因为在Oracle中,dba_objects 是一个数据字典视图,通常只有具有DBA权限的用户才能访问。如果当前用户没有访问这个视图的权限,我们可以使用替代方案,比如 all_objects 或 user_objects,但这取决于我们需要查看的对象范围。 然而,在查询锁定对象时,我们通常需要查看整个数据库中被锁定的对象,因此最好使用 dba_objects。如果权限不足,我们可以采取以下措施: 1. 向当前用户授予访问DBA视图的权限(需要DBA权限): ```sql GRANT SELECT ON dba_objects TO your_user; ``` 2. 如果无法获得DBA权限,我们可以尝试使用 all_objects 视图,但注意,all_objects 只显示当前用户有权限访问的对象,可能不包括其他用户的对象。 3. 使用 sys.dba_objects(如果当前用户有访问sys模式的权限)。 但是,在查询锁定的对象时,v$locked_object 视图中的 object_id 对应的对象可能属于任何用户,因此如果没有DBA权限,我们可能无法直接通过 dba_objects 来连接。 替代方案:使用 all_objects 可能无法获取到所有对象,因为当前用户可能没有访问某些对象的权限。因此,我们可能需要请求DBA协助。 另外,我们可以尝试使用其他视图来获取锁定信息,比如 v$session 和 v$lock 结合,然后通过 v$session 中的 ROW_WAIT_OBJ# 来获取对象ID,再通过 all_objects 或 user_objects 来解析对象名(但同样有权限问题)。 这里提供一个替代查询,它使用 v$lock 和 v$session 来获取锁信息,并尝试通过 dba_objects 获取对象名(如果权限允许的话)。如果权限不足,我们可以只显示对象ID,然后让有权限的用户去查询对象名。 如果确实没有权限,我们可以这样查询: ```sql SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, l.id1 AS object_id, -- 显示对象ID l.type, DECODE(l.lmode, 0, 'None', 1, 'Null', 2, 'Row-S (SS)', 3, 'Row-X (SX)', 4, 'Share', 5, 'S/Row-X (SSX)', 6, 'Exclusive', TO_CHAR(l.lmode) ) AS lock_mode, DECODE(l.request, 0, 'None', 1, 'Null', 2, 'Row-S (SS)', 3, 'Row-X (SX)', 4, 'Share', 5, 'S/Row-X (SSX)', 6, 'Exclusive', TO_CHAR(l.request) ) AS lock_request, l.ctime AS time_held, l.block AS blocking_others FROM v$lock l JOIN v$session s ON l.sid = s.sid WHERE l.type IN ('TM', 'TX') -- 我们关注事务锁和表锁 AND l.lmode >= 0; -- 排除None锁 ``` 这个查询不会显示对象名称,但会显示对象ID(object_id)。然后,我们可以根据对象ID让有权限的用户去查询对象名。 如果当前用户有访问 all_objects 的权限,我们可以尝试用 all_objects 替换 dba_objects,但注意,all_objects 只包含当前用户有权限的对象。因此,我们修改原始查询为: ```sql SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, o.object_name, l.locked_mode, l.oracle_username FROM v$locked_object l JOIN all_objects o ON l.object_id = o.object_id JOIN v$session s ON l.session_id = s.sid; ``` 但是,如果被锁定的对象不在当前用户的权限范围内,那么这些对象将不会出现在 all_objects 中,因此我们可能无法看到所有被锁定的对象。 因此,最佳解决方案是申请DBA权限或让DBA执行查询。 如果以上方法都不可行,我们可以使用以下查询,它不依赖于 dba_objects 或 all_objects,但只能提供对象ID: ```sql SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, l.object_id, -- 对象ID l.locked_mode, l.oracle_username FROM v$locked_object l JOIN v$session s ON l.session_id = s.sid; ``` 然后,我们可以根据 object_id 让有权限的用户查询对象名: ```sql SELECT owner, object_name, object_type FROM dba_objects WHERE object_id = :object_id; ``` 或者,如果当前用户有访问 all_objects 的权限,也可以: ```sql SELECT owner, object_name, object_type FROM all_objects WHERE object_id = :object_id; ``` 综上所述,根据当前用户的权限情况,我们可以选择不同的查询方式。 如果问题是要解决“dba_objects不存在”的错误,我们可以使用上述替代查询。 因此,我们给出一个不依赖dba_objects的查询,只显示对象ID: ```sql SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, l.object_id, -- 这里显示对象ID l.locked_mode, l.oracle_username FROM v$locked_object l JOIN v$session s ON l.session_id = s.sid; ``` 然后,如果需要对象名称,再根据对象ID单独查询。 注意:v$locked_object 视图中的 object_id 就是 dba_objects 中的 object_id。 另外,我们也可以尝试使用 sys.obj$ 系统表,但这需要更高的权限,而且不推荐直接查询系统表。 所以,我们建议使用显示对象ID的查询,然后让有权限的用户去解析对象名。 如果当前环境允许,我们可以创建一个函数来将对象ID转换为对象名(但同样需要权限)。 最后,如果我们需要在应用程序中自动解析对象名,我们可以先尝试使用 all_objects,如果查不到,则说明权限不足,就只显示对象ID。 下面是一个PL/SQL函数示例,用于根据对象ID获取对象名(需要当前用户有访问 all_objects 的权限): ```sql CREATE OR REPLACE FUNCTION get_object_name(p_object_id IN NUMBER) RETURN VARCHAR2 IS v_object_name VARCHAR2(128); BEGIN SELECT object_name INTO v_object_name FROM all_objects WHERE object_id = p_object_id; RETURN v_object_name; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN 'Unknown object or no privilege'; WHEN OTHERS THEN RETURN 'Error: ' || SQLERRM; END; / ``` 然后在查询中使用: ```sql SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, l.object_id, get_object_name(l.object_id) AS object_name, -- 调用函数 l.locked_mode, l.oracle_username FROM v$locked_object l JOIN v$session s ON l.session_id = s.sid; ``` 但是,这个函数仍然可能因为权限问题无法获取到对象名,所以返回错误信息。 综上所述,根据权限情况,我们选择不同的策略。在没有DBA权限且无法访问dba_objects时,我们只能显示对象ID,或者尝试使用all_objects(可能不完整)。 因此,我们给出一个健壮的查询方案,它尝试获取对象名,如果失败则显示对象ID和错误信息: ```sql SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, l.object_id, COALESCE(o.object_name, 'Unknown: ' || l.object_id) AS object_name, l.locked_mode, l.oracle_username FROM v$locked_object l JOIN v$session s ON l.session_id = s.sid LEFT JOIN all_objects o ON l.object_id = o.object_id; ``` 这个查询使用左连接 all_objects,如果找不到对象名,则显示 'Unknown: ' 加上对象ID。 这样,即使有些对象名无法解析,我们也能看到对象ID,从而可以进一步排查。 注意:这个查询要求当前用户至少具有访问 v$locked_object, v$session 和 all_objects 的权限,这些权限通常比 dba_objects 更容易获得。 如果当前用户没有访问 all_objects 的权限,那么我们需要申请以下权限: ```sql GRANT SELECT ON all_objects TO current_user; ``` 或者,如果当前用户没有访问 v$session 和 v$locked_object 的权限,还需要: ```sql GRANT SELECT ON v_$session TO current_user; GRANT SELECT ON v_$locked_object TO current_user; ``` 在Oracle中,v$session 和 v$locked_object 是动态性能视图,通常需要授予 SELECT ON v_$session 而不是 v$session。 总结:由于原始查询中的 dba_objects 视图不存在(可能是权限问题),我们提供了替代方案,使用 all_objects 或直接显示对象ID,并给出了相应的查询语句。</think>以下是针对 "dba_objects 表或视图不存在" 问题的完整解决方案,包含替代查询方案、权限修复方法和诊断工具: ### 1. 替代查询方案(使用 `all_objects`) ```sql -- 使用 all_objects 替代 dba_objects SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, o.owner || '.' || o.object_name AS full_object_name, l.locked_mode, l.oracle_username FROM v$locked_object l JOIN all_objects o ON l.object_id = o.object_id JOIN v$session s ON l.session_id = s.sid; ``` ### 2. 权限修复方案(需要DBA权限) ```sql -- 授予当前用户访问数据字典的权限 GRANT SELECT ON dba_objects TO your_username; GRANT SELECT ON v_$locked_object TO your_username; GRANT SELECT ON v_$session TO your_username; -- 创建同义词解决访问问题 CREATE PUBLIC SYNONYM dba_objects FOR sys.dba_objects; CREATE PUBLIC SYNONYM v$locked_object FOR sys.v_$locked_object; CREATE PUBLIC SYNONYM v$session FOR sys.v_$session; ``` ### 3. 权限诊断脚本 ```sql -- 检查当前用户的权限 SELECT * FROM session_privs; SELECT * FROM session_roles; -- 检查对象访问权限 SELECT * FROM all_tab_privs WHERE table_name IN ('DBA_OBJECTS', 'V_$LOCKED_OBJECT', 'V_$SESSION'); -- 检查同义词是否存在 SELECT * FROM all_synonyms WHERE synonym_name IN ('DBA_OBJECTS', 'V$LOCKED_OBJECT', 'V$SESSION'); ``` ### 4. 低权限用户查询方案 ```sql -- 使用基础视图查询锁定信息 SELECT s.sid, s.serial#, s.username, s.osuser, s.machine, s.program, l.id1 AS object_id, DECODE(l.type, 'TM', 'DML Enqueue', 'TX', 'Transaction', 'UL', 'User-defined', l.type) AS lock_type, DECODE(l.lmode, 0, 'None', 1, 'Null', 2, 'Row-S', 3, 'Row-X', 4, 'Share', 5, 'S/Row-X', 6, 'Exclusive', l.lmode) AS lock_mode FROM v$lock l JOIN v$session s ON l.sid = s.sid WHERE l.type IN ('TM', 'TX'); ``` ### 5. 对象ID转对象名函数(PL/SQL) ```sql CREATE OR REPLACE FUNCTION get_object_name(p_object_id IN NUMBER) RETURN VARCHAR2 IS v_object_name VARCHAR2(128); BEGIN BEGIN -- 尝试从dba_objects获取 SELECT owner || '.' || object_name INTO v_object_name FROM dba_objects WHERE object_id = p_object_id; EXCEPTION WHEN NO_DATA_FOUND THEN -- 尝试从all_objects获取 SELECT owner || '.' || object_name INTO v_object_name FROM all_objects WHERE object_id = p_object_id; WHEN OTHERS THEN v_object_name := 'UNKNOWN: ' || p_object_id; END; RETURN v_object_name; END; / -- 使用函数查询 SELECT s.sid, s.serial#, s.username, get_object_name(l.id1) AS object_name, l.lmode AS lock_mode FROM v$lock l JOIN v$session s ON l.sid = s.sid WHERE l.type = 'TM'; ``` ### 权限问题分析: | 问题类型 | 原因 | 解决方案 | |----------|------|----------| | **缺少对象权限** | 用户没有SELECT权限 | `GRANT SELECT ON dba_objects TO user` | | **缺少系统权限** | 没有SELECT_CATALOG_ROLE | `GRANT SELECT_CATALOG_ROLE TO user` | | **同义词缺失** | 公共同义词不存在 | `CREATE PUBLIC SYNONYM ...` | | **视图不存在** | 数据库未创建视图 | 运行`catalog.sql`和`catproc.sql` | ### 最佳实践: 1. **创建专用监控角色**: ```sql CREATE ROLE lock_monitor; GRANT SELECT ON v_$session TO lock_monitor; GRANT SELECT ON v_$lock TO lock_monitor; GRANT SELECT ON dba_objects TO lock_monitor; GRANT lock_monitor TO your_user; ``` 2. **使用AWR报告分析锁问题**: ```sql -- 生成AWR报告 SELECT * FROM TABLE(DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML( (SELECT dbid FROM v$database), (SELECT instance_number FROM v$instance), (SELECT snap_id - 1 FROM dba_hist_snapshot ORDER BY snap_id DESC FETCH FIRST 1 ROW ONLY), (SELECT snap_id FROM dba_hist_snapshot ORDER BY snap_id DESC FETCH FIRST 1 ROW ONLY))); ``` 3. **应用程序端锁监控(Java示例)**: ```java public void monitorLocks(Connection conn) throws SQLException { String sql = "SELECT sid, serial#, username, osuser, program, " + "get_object_name(object_id) AS object_name " // 使用前面创建的函数 + "FROM v$session s " + "JOIN v$lock l ON s.sid = l.sid " + "WHERE l.type = 'TM'"; try (PreparedStatement stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery()) { while (rs.next()) { System.out.println("Lock detected: " + "SID=" + rs.getInt("sid") + ", Object=" + rs.getString("object_name") + ", User=" + rs.getString("username")); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值