如何查看正在执行的实际Oracle SQL语句

时间:2020-03-05 18:51:15  来源:igfitidea点击:

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

我被要求为现有报告的变体定义规格(例如,应用其他过滤器来约束数据集,并略微修改版式)。原则上,这听起来很简单,但是如果没有任何现有文档,这很难做到。

据我了解,日志无济于事,因为报告只查询数据库;它实际上不会插入,删除或者更新数据库值,因此没有什么可记录的(这是正确的吗?)。

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

解决方案

回答

我认为V $ SQLAREA表包含我们要查找的内容(请参见SQL_TEXT和SQL_FULLTEXT列)。

回答

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

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

需要注意的一件事是,使用参数的查询将在以下条目中显示一次

and TABLETYPE=’:b16’

而其他不显示的内容则会出现多次,例如:

and TABLETYPE=’MT’

这些表的一个示例是使用以下SQL查找前20个磁盘读取猪的SQL。我们可以通过删除WHERE rownum <= 20并添加ORDER BY模块来更改此设置。我们通常会发现该模块将为我们提供有关正在运行该查询的软件的沼泽线索(例如:" TOAD 9.0.1.8"," JDBC Thin Client"," 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
;

回答

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

[编辑]该死的另外两个答案。下次必须键入更快;-)

回答

对不起,简短的答案,但是来晚了。 Google" oracle事件10046 sql跟踪"。最好跟踪单个会话,因为如果它是共享sql并被多个用户使用,则从v $ sql确定哪个SQL属于哪个会话并不容易。

如果我们想打动Oracle DBA朋友,请学习如何使用事件10046设置oracle跟踪,解释wait事件的含义并找到最主要的cpu​​使用者。

Quest有一个免费的产品,可以让我们捕获从客户端发出的SQL,但不确定它是否适用于Oracle产品/版本。谷歌为此"查询oracle sql监视器"。

晚安。

回答

我在Java应用程序中遇到了类似的问题。我围绕Oracle驱动程序编写了JDBC驱动程序包装程序,以便将所有输出发送到日志文件。

回答

-我使用类似的东西,包括一些概念和一些从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) 

           FROM 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(DECODE(PIECE,  1,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE,  2,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE,  3,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE,  4,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE,  5,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE,  6,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE,  7,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE,  8,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE,  9,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 10,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 11,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 12,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 13,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 14,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 15,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 16,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 17,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 18,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 19,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 20,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 21,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 22,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 23,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 24,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 25,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 26,SQL_TEXT,NULL)) ||

                   MAX(DECODE(PIECE, 27,SQL_TEXT,NULL)) ||

                   MAX(DECODE(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;