3

I am trying to trace the SQL statements executed against a particular database user. I don't have AUDITING enabled and I am using Oracle 11g.

I have the following query :

SELECT  
  S.MODULE, 
  SQL_TEXT , 
  S.EXECUTIONS    
FROM
  SYS.V_$SQL S, 
  SYS.ALL_USERS U
WHERE
  S.PARSING_USER_ID=U.USER_ID 
  AND UPPER(U.USERNAME) IN ('USERNAME')
  AND (UPPER(s.MODULE)='APP.EXE')
ORDER BY S.LAST_LOAD_TIME

But if multiple users running the 'APP.EXE' are connected to the same db user, I am not able to understand which OS user executed which query. So I tried to join with V$SESSION view to get the user details.

SELECT  
  S.MODULE,SQL_TEXT ,SN.OSUSER, SN.MACHINE, S.EXECUTIONS
FROM
  SYS.V_$SQL S, 
  SYS.ALL_USERS U,
  V$SESSION SN 
WHERE
  S.PARSING_USER_ID=U.USER_ID 
  AND UPPER(U.USERNAME) IN ('USERNAME')
  AND (UPPER(S.MODULE)='APP.EXE')
  AND S.SQL_ID=SN.SQL_ID
ORDER BY S.LAST_LOAD_TIME

But this doesn't seems to be working(In my case it didn't return any rows) So, I have the following questions

1) How do I get the queries executed by each session?

2) The EXECUTIONS column of V_$SQL seems to the executions from all the sessions. How do I know the number of times a particular query is executed by a session?

3) How long a record about a query will be stored in V_$SQL? When do Oracle delete it from the view?

Thanking you all in advance,

Pradeep

Burhan Ali
  • 2,258
  • 1
  • 28
  • 38
Pradeep
  • 299
  • 2
  • 8
  • 15

3 Answers3

6

You're probably not going to get the data that you're looking for without doing more configuration (such as enabling auditing) or making some compromises. What is the business problem you're trying to solve? Depending on the problem, we may be able to help you identify the easiest approach to configuring the database to be able to record the information you're after.

Oracle does not attempt to store anywhere how many times a particular user (and particularly not how many times a particular operating system user) executed a particular query. The SQL_ID in V$SESSION only indicates the SQL_ID that the session is currently executing. If, as I'm guessing, this is a client-server application, it is quite likely that this is NULL 99% of the time because the vast majority of the time, the session is not executing any SQL, it's waiting on the user to do something. The PREV_SQL_ID in V$SESSION is the prior SQL statement that was executed-- that at least won't generally be NULL. But it's only going to have one value, it's not going to have a history of the SQL statements executed by that session.

The V$SQL view is a representation of what is in the SQL shared pool. When a SQL statement ages out of the shared pool, it will no longer be in the V$SQL view. How quickly that happens depends on a multitude of factors-- how frequently someone is executing the statement, how frequently new statements are parsed (which generally depends heavily on whether your applications are using bind variables correctly), how big your shared pool is, etc. Generally, that's going to be somewhere between a few minutes and until the database shuts down.

If you are licensed to use the AWR tables and you are interested in approximations rather than perfectly correct answers, you might be able to get the information you're after by looking at some of the AWR tables. For example, V$ACTIVE_SESSION_HISTORY will capture the SQL statement that each session was actively executing each second. Since this is a client-server application, however, that means that the vast majority of the time, the session is going to be inactive, so nothing will be captured. The SQL statements that do happen to get captured for a session, though, will give you some idea about the relative frequency of different SQL statements. Of course, longer-running SQL statements are more likely to be captured as well since they are more likely to be active on a given instant. If query A and B both execute in exactly the same amount of time and a session was captured executing A 5 times and B 10 times in the last hour, you can conclude that B is executed roughly twice as often as A. And if you know the average execution time of a query, the average probability that the query was captured is going to be the number of seconds that the query executes (a query that executes in 0.5 seconds has a 50% chance of getting captured, one that executes in 0.25 seconds has a 25% chance of getting captured) so you can estimate how often a particular session executed a particular query. That is far from an exact number particularly over shorter time-frames and for queries whose actual execution times are more variable.

The data in V$ACTIVE_SESSION_HISTORY view is generally available for a few hours. It then gets sampled down into the DBA_HIST_ACTIVE_SESS_HISTORY table which cuts the amount of data available by an order of magnitude making any estimates much less accurate. But that data is kept for whatever your AWR retention interval is (by default, that's one week though many sites increase it to 30 or 60 days).

Justin Cave
  • 227,342
  • 24
  • 367
  • 384
  • Note that `prev_sql_id` might not just hold the last sql as we would expect, I see inserts into `SYS.AUD$` being associated with that id. – YoYo Mar 14 '17 at 23:33
1

According to oracle documentation

SQL_ADDRESS -Used with SQL_HASH_VALUE to identify the SQL statement that is currently being  executed 

SQL_HASH_VALUE - Used with SQL_ADDRESS to identify the SQL statement that is currently being executed 

Please find the below link for reference

SQL_ADDRESS and HASH VALUE

Kindly modify the SQL below

    SELECT S.MODULE, SQL_TEXT, SN.OSUSER, SN.MACHINE, S.EXECUTIONS
      FROM SYS.V_$SQL S, SYS.ALL_USERS U, V$SESSION SN
     WHERE S.PARSING_USER_ID = U.USER_ID
       AND UPPER(U.USERNAME) IN ('USERNAME')
       AND (UPPER(S.MODULE) = 'APP.EXE')
       AND SN.sql_hash_value = S.hash_value
       AND SN.sql_address = S.address
     ORDER BY S.LAST_LOAD_TIME
psaraj12
  • 4,772
  • 2
  • 21
  • 30
  • 2
    This won't change the result. Joining on `hash_value` and `address` was the old way to join those tables before `sql_id` was introduced. It will still work with the old approach, it just won't change the result. You're still not going to get, at most, the current SQL statement that the session is executing. – Justin Cave Jul 10 '12 at 16:15
0

Try this

SELECT l.Sql_Id
FROM v$session s
JOIN v$session_longops l 
    ON l.sid = s.Sid 
    AND l.Serial# = s.Serial# 
    AND l.Start_Time >= s.Logon_Time
WHERE s.Audsid = Sys_Context('USERENV', 'SESSIONID')

I assume you are interested only in log running sql's?

VBoka
  • 8,995
  • 3
  • 16
  • 24
Žilvinas
  • 71
  • 2