28

我正在使用一个定制的内部应用程序,它每周生成一组标准报告。我无法访问应用程序的源代码,每个人都告诉我没有可用于 Oracle 数据库模式的文档。(啊!)

我被要求为现有报告的变体定义规范(例如,应用额外的过滤器来约束数据集,并稍微修改布局)。这在原则上听起来很简单,但是如果没有任何现有的文档就很难。

我的理解是日志不能帮助我,因为报告只查询数据库;它实际上并没有插入、删除或更新数据库值,所以没有什么要记录的(这是正确的吗?)。

所以我的问题是:是否有工具或实用程序(Oracle 或其他)可以用来查看在报告生成作业仍在运行时正在执行的实际 SQL 语句?我想,如果我可以看到实际访问了哪些表来生成现有报告,我将有一个很好的起点来探索架构并确定用于我自己的报告的正确 SQL。

4

6 回答 6

24

在数据字典方面,您可以使用很多工具,例如Schema Spy

要查看正在运行的查询,请查看视图 sys.v_$sql 和 sys.v_$sqltext。您还需要访问 sys.all_users

需要注意的一件事是,使用参数的查询将显示一次,并带有类似的条目

and TABLETYPE=’:b16’

而其他不会出现多次的,例如:

and TABLETYPE=’MT’

这些表的一个实际示例是以下 SQL,用于查找前 20 个磁盘读取消耗量最大的问题。您可以通过删除WHERE rownum <= 20并添加ORDER BY 模块来更改此设置。您经常会发现该模块会给您提供有关正在运行查询的软件的错误线索(例如:“TOAD 9.0.1.8”、“JDBC 瘦客户端”、“runcbl@somebox (TNS V1-V3)”等)

SELECT 
 module, 
 sql_text, 
 username, 
 disk_reads_per_exec, 
 buffer_gets, 
 disk_reads, 
 parse_calls, 
 sorts, 
 executions, 
 rows_processed, 
 hit_ratio, 
 first_load_time, 
 sharable_mem, 
 persistent_mem, 
 runtime_mem, 
 cpu_time, 
 elapsed_time, 
 address, 
 hash_value 
FROM 
  (SELECT
   module, 
   sql_text , 
   u.username , 
   round((s.disk_reads/decode(s.executions,0,1, s.executions)),2)  disk_reads_per_exec, 
   s.disk_reads , 
   s.buffer_gets , 
   s.parse_calls , 
   s.sorts , 
   s.executions , 
   s.rows_processed , 
   100 - round(100 *  s.disk_reads/greatest(s.buffer_gets,1),2) hit_ratio, 
   s.first_load_time , 
   sharable_mem , 
   persistent_mem , 
   runtime_mem, 
   cpu_time, 
   elapsed_time, 
   address, 
   hash_value 
  FROM
   sys.v_$sql s, 
   sys.all_users u 
  WHERE
   s.parsing_user_id=u.user_id 
   and UPPER(u.username) not in ('SYS','SYSTEM') 
  ORDER BY
   4 desc) 
WHERE
 rownum <= 20;

请注意,如果查询很长.. 您将不得不查询 v_$sqltext。这将存储整个查询。您将不得不查找 ADDRESS 和 HASH_VALUE 并拾取所有部分。例如:

SELECT
 *
FROM
 sys.v_$sqltext
WHERE
 address = 'C0000000372B3C28'
 and hash_value = '1272580459'
ORDER BY 
 address, hash_value, command_type, piece
;
于 2008-09-11T06:45:01.540 回答
8

很抱歉简短的回答,但已经晚了。谷歌“oracle 事件 10046 sql 跟踪”。最好跟踪单个会话,因为如果它是共享 sql 并被多个用户使用,那么从 v$sql 确定哪个 SQL 属于哪个会话并不容易。

如果您想给您的 Oracle DBA 朋友留下深刻印象,请学习如何使用事件 10046 设置 Oracle 跟踪,解释等待事件的含义并找到最高 cpu 消费者。

Quest 有一个免费产品,允许您在 SQL 从客户端发出时捕获它,但不确定它是否适用于您的产品/版本的 Oracle。谷歌“quest oracle sql monitor”为此。

晚安。

于 2008-09-11T06:59:55.793 回答
3

我认为V$SQLAREA表包含您要查找的内容(请参见SQL_TEXTSQL_FULLTEXT列)。

于 2008-09-11T06:44:44.397 回答
2

是的,这绝对是可能的。v$sql 视图包含该信息。像这段代码这样的东西应该为您指明正确的方向。我自己还没有尝试过那段特定的代码——现在离 Oracle 数据库还很远。

[编辑]该死的已经有另外两个答案了。下次必须打字更快;-)

于 2008-09-11T06:46:04.720 回答
1

- 我使用类似的东西,概念和一些从 asktom 窃取的代码。
-- 欢迎提出改进建议

WITH
sess AS
(
SELECT *
FROM V$SESSION
WHERE USERNAME = USER
ORDER BY SID
)
SELECT si.SID,
si.LOCKWAIT,
si.OSUSER,
si.PROGRAM,
si.LOGON_TIME,
si.STATUS,
(
SELECT ROUND(USED_UBLK*8 /1024,1)
从 V$TRANSACTION,
sess
WHERE sess.TADDR = V$TRANSACTION.ADDR
AND sess.SID = si.SID

) rollback_remaining,

(
SELECT (MAX(DECODE(PIECE, 0,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 1,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 2,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 3,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 4,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 5,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 6,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 7,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 8,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 9,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 10,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 11,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 12,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 13,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 14,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 15,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 16,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 17,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 18,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 19,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 20,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 21,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 22,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 23,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 24,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 25,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 26,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 27,SQL_TEXT,NULL)) ||
MAX(解码(PIECE, 28,SQL_TEXT,NULL)) ||
MAX(DECODE(PIECE, 29,SQL_TEXT,NULL)))
FROM V$SQLTEXT_WITH_NEWLINES
WHERE ADDRESS = SI.SQL_ADDRESS AND
PIECE < 30
) SQL_TEXT
FROM sess si;

于 2008-09-16T17:00:57.883 回答
0

我在 Java 应用程序中有(有)类似的问题。我围绕 Oracle 驱动程序编写了一个 JDBC 驱动程序包装器,因此所有输出都发送到一个日志文件。

于 2008-09-16T14:51:45.197 回答