oracle - Session execute a specified query - oracle

Today, someone in my system has updated unexpected statement. So that makes my system run incorrect.
Now, I would like to see log who (or which session) did it. May I find it in AWR report ? And if I can find it in AWR report, where is it particularly ?
Thanks so much !

The change could be in many sources, depending on how it was made. Only the last option, Log Miner, will give you exactly everything you want. But it also requires the most effort. Some sources won't tell you the session, but maybe just seeing the relevant SQL will be enough to figure out who did it.
V$SQL - All SQL statements go in there, but they age out of the shared pool so you need to search quickly. If they used a unique query you may be able to find it with something like select * from v$sql where lower(sql_text) like '%table_name%';.
AWR - You may be able to find the SQL in select * from dba_hist_sqltext where lower(sql_text) like '%table_name%';, and then if you're lucky you can find out some session information from select * from dba_hist_active_sess_history where sql_id = '<sql id>';. Active Session History only samples activity, if the query ran very quickly there's a good chance it won't be in there.
Flashback query - If you're lucky the UNDO is still around and you can see exactly how it changed from a flashback query. This may give you the exact time, and what changed. select VERSIONS_STARTSCN, VERSIONS_STARTTIME, VERSIONS_ENDSCN, VERSIONS_ENDTIME, VERSIONS_XID, VERSIONS_OPERATION, your_table.* from your_table versions between scn minvalue and maxvalue;
Log Miner - I haven't used this, but supposedly it's the perfect tool for this job. Read more about it in the documentation.

Related

SQL Plan change reasons

One of the job schedulers is running in the production environment on a daily basis which use to take only 20 mins based past execution history, but today it's been more than 2 hours still not completed.
a) How to check whether the SQL plan has changed today or not?
b) What could be the reasons for the plan change? One I know due to code change. What else could cause plan change?
You can check if the SQL execution plan has changed by using the Active Workload Repository (AWR). First, you need to find the SQL_ID for the relevant query. The view GV$SQL contains the most recent SQL. If you can't find the query in this view, try DBA_HIST_SQLTEXT instead.
select sql_id, sql_text
from gv$sql
where lower(sql_fulltext) like '%some unique string%';
With the SQL_ID, you can start investigating historical information. The table DBA_HIST_SQLSTAT contains lots of summary information about the SQL. The most important column is PLAN_HASH_VALUE; if that value changes, then the execution plan has changed.
select snap_id, sql_id, plan_hash_value, executions_delta, elapsed_time_delta/100000 seconds_delta
,dba_hist_sqlstat.*
from dba_hist_sqlstat
--join to dba_hist_snapshot if you want to find precise times instead of SNAP_IDs.
where sql_id = '&SQL_ID'
order by dba_hist_sqlstat.snap_id;
If the plan has changed, you can view both plans with this:
select * from table(dbms_xplan.display_awr(sql_id => '&SQL_ID'));
Unfortunately, the most difficult part of query tuning with Oracle is that there are a dozen different ways to view the execution plans, and each of them provides slightly different data.
This query only returns numbers for the last execution, but it returns actual numbers and times, which helps you focus on the specific operation and wait events that caused the problem.
select dbms_sqltune.report_sql_monitor(sql_id => '&SQL_ID', type => 'text') from dual;
This query returns some additional execution plan information, specifically the Note section. Most graphical IDEs leave out that section, but it's vital for complex troubleshooting. If something weird is going on, the Note section will often explain why.
select * from table(dbms_xplan.display_cursor(sql_id => '&SQL_ID'));
There are many reasons why execution plans can change. If you add additional information to the question I may be able to make an educated guess.
Quick Check :
Please check whether the Statistics, is upto Date, both System and Table statistics.
Pleae check if any changes to table or index made ?

Extract sql_id from hash_value

I have sql hash value of a query.
I don't have the sqltext, plan hash or sql_id - only the hash value of the sql.
When I'm querying the v$sql view there are no result (I guess the sql is not in the memory already):
select * from v$sql where hash_value = 'hv_Example';
Is there a way to achieve the sql_id from the hash_value?
I didn't found a view that holds the hash value and the sql_id togather...
V$SQL contains both HASH_VALUE and SQL_ID, but not forever.
According to Tanel Poder's blog, the HASH_VALUE can be derived from the SQL_ID, but the inverse operation is not possible. But converting HASH_VALUE to SQL_ID wouldn't solve your problem anyway.
First of all, I'm not sure why you would have access to the HASH_VALUE but not the SQL_ID. The SQL_ID is much more commonly used for performance tuning. Whatever program or source is providing the HASH_VALUE should be modified to return the SQL_ID instead.
But the real problem here, whichever value you have, is that data is not permanently stored in V$SQL. As statements get old they are aged out of the shared pool, and disappear from V$SQL. Also, if you're using a clustered system, make sure you're using GV$SQL.
If you are using Enterprise Edition, and have licensed the Oracle Diagnostic Pack, you may be able to find historical SQL_ID values with one of these two statements:
select sql_id
from gv$active_session_history
where sql_full_plan_hash_value = 'XYZ';
select sql_id
from dba_hist_active_sess_history
where sql_full_plan_hash_value = 'XYZ';
Data in GV$ACTIVE_SESSION_HISTORY typically lasts for about a day. Data in DBA_HIST_* stays for 8 days by default, but is configurable. You can check the AWR retention with this query: select retention from dba_hist_wr_control;
If the HASH_VALUE is less old than the retention period, but still not in AWR, then you can probably ignore it. ASH and AWR use sampling, which means they do not capture everything that happens in a database. ASH takes a sample every second and AWR takes a sample every 10 seconds.
A lot of people struggle with this concept but it's helpful to come to terms with the idea of sampling. Systems that capture all of the information, like tracing everything, are overwhelming and use up too much space and processing power. If we're looking at performance problems then we do not care about something that doesn't happen for more than 10 seconds out of 8 days.

SDO_JOIN table join on large tables no longer returns results after upgrade from Oracle 11.2.0.1 to 11.2.0.4

I have the same database on 2 different Oracle servers, one is 11.2.0.1.0 and the other is 11.2.0.4.0.
I have the same 2 geometry tables in both databases and run the following query on both servers. When run on an 11.2.0.1.0 version of Oracle, the query runs for a few minutes and I get results, the same query when run on 11.2.0.4.0 runs for about 3 seconds and returns no results.
The BLPUs table holds 36 million points and the PD_B2 table holds a polygon. I am trying to find all the points that fall in the polygon.
Other spatial queries do return rows but it takes hours and hours whereas the table join suggested in the Oracle Spatial documentation, takes 15 minutes to return all the points.
SELECT /*+ ordered */ a.uprn
FROM TABLE(SDO_JOIN('BLPUS', 'GEOLOC', 'PD_B2', 'GEOLOC','mask=ANYINTERACT')) c, blpus a, PD_B2 b
WHERE c.rowid1 = a.rowid
AND c.rowid2 = b.rowid;
The spatial queryies below return SDO_ROWIDSET() when run on the 11.2.0.4 server
select SDO_JOIN('BLPUS', 'GEOLOC', 'PD_B2', 'GEOLOC','mask=ANYINTERACT')
from dual;
select SDO_JOIN('BLPUS', 'GEOLOC', 'PD_B2', 'GEOLOC')
from dual;
On the 11.2.0.1 server they return results.
I have discovered that a much smaller table of points will work on 11.2.0.4 so it seems that there is a size limit on 11.2.0.4 when using SDO_JOIN where as 11.2.0.1 seems to cope with the large table.
Does anyone know why this is or if there is an actual limit on table size when using SDO_JOIN?
This is strange. I see no reason why SDO_JOIN will not work the same way in 11.2.0.4. At least I have not seen that sort of behavior before. It looks like a bug to me and I suggest you file a service request with Oracle Support so we can take a look. You may need to provide a dump of the tables - or at least of a small enough subset that demonstrates the problem.
That said there are a few things to check: did you apply the 11.2.0.4 patch on the same database ? I.e. nothing changed in terms of table structures or content, grants, etc ?
When you say that the query returns no rows, does it do so immediately ? Or does it perform some processing before completing without anything being returned ?
How large is the PD_B2 table ?
What happens when you do:
select SDO_JOIN('BLPUS', 'GEOLOC', 'PD_B2', 'GEOLOC','mask=ANYINTERACT')
from dual;
Does this also return nothing ?
What happens if you do
select SDO_JOIN('BLPUS', 'GEOLOC', 'PD_B2', 'GEOLOC')
from dual;
Both should return something that looks like this:
SDO_ROWIDSET(SDO_ROWIDPAIR('AAAW3LAAGAAAADmAAu', 'AAAW3TAAGAAAAg7AAC'), SDO_ROWIDPAIR('AAAW3LAAGAAAADmABE', 'AAAW3TAAGAAAAgrAAA'),...)
You will see this if you run the query in sqlplus. [If you use a GUI (like TOAD or SQLDeveloper) then you may not see that. All those GUIs have problems dealing with objects or arrays.]
But the fact that your 11.2.0.4 tests complete very quickly probably means that you get an empty result back, maybe like this:
SDO_ROWIDSET()
and that confirms that something did not work.
Now, from what you say PD_B2 only contains one row ? If so then there is no reason whatsoever to go via SDO_JOIN. A straightforward spatial query is easier to write. SDO_JOIN only makes sense when both tables being joined contain multiple rows. Then again, if one of the tables is very small (like the PD_B2 table in your case), then it anyway falls back to a simple query.
A simple query would look like this:
SELECT a.uprn
FROM blpus a, PD_B2 b
WHERE sdo_anyinteract (a.geoloc, b.geoloc) = 'TRUE';
Does this return what you expect in 11.2.0.4 ?
You may also want to examine the cost of the query and the query plan used. In sqlplus, do this:
set timing on
set autotrace traceonly
then run the above query. The effect is that sqlplus will not display any results - but it will still fetch and format the output: it will just not print them. At the end you will get a printout of the query plan used as well as some execution statistics and the elapsed time. Please add those results to your question.
Running the query from within your application should have a similar profile: similar response time and database-side costs - assuming you do fetch all the 1.3 million rows.
BTW, what do you do with those results ? Do you show them out as a report ? Do you save them into a table for later analysis ? Surely you do not want to show them all on a map ?
To clarify: SDO_JOIN is only for matching many to many geometries. For matching one to many, the simple SDO_ANYINTERACT() is what you need. As a matter of fact, SDO_JOIN will automatically fall back to a simple SDO_ANYINTERACT when one of the sets is very much smaller than the other. I can't see how SDO_JOIN could be faster in your circumstances (i.e. when searching for all objects that match one object) since it will perform the same as an SDO_ANYINTERACT and will require extra joins to the two tables.
Going back to the original issue - that of a difference in behavior in SDO_JOIN between 11.2.0.1 and 11.2.0.4 that IMO is definitely a bug that you need to report to Oracle Support.

Oracle DB audit trails

Someone (or something) actually updated a value in my table wrongly. I am trying to find out when the update happened. Unfortunately, there is no audit trigger being created for the said table.
Is there other ways or logs that I can check and verify what SQL statements were run at what time?
I had tried to look at v$sql table, but I don't think that table is capturing all the SQL statements being performed on the database. E.g. I specifically did an UPDATE statement, but it is not captured in the v$sql table.
Can I look at the redo.log? However, I do not know how to interpret this log.
Your only real option is logminer, which isn't for the faint of heart.
The documentation is here: http://docs.oracle.com/cd/B19306_01/server.102/b14215/logminer.htm
v$sql rows may get aged out after a while. Did you account for case sensitivity when looking in v$sql?
select * from v$sql where upper(sql_fulltext) like '%UPDATE%';

How to get the Name of the Table with SELECT DELETE INSERT UPDATE operation

I want a tool or solution to find out the affected table on running the procedure|Function or package Given the PL/SQL code.
This is require for me to comeup with the better testcase by knowing which all the tables will be affected by running the code and what all the operation performed on them.
The solution should even work for Procedure calling Procedure.
OutPut may be:
SELECT FROM: TABLE1
DELETE FROM: TABLE2
INSERT INTO: TABLE3
CALL AnotherPROC:
SELECT FROM: TABLE4
DELETE FROM: TABLE5
Thanks in Advance:
For a pre-run analysis if you are running a stored procedure/package/function then the DBA_DEPENDENCIES table can tell you which objects "depend" on it, but that doesn't mean they may necessarily be affected because the program control can take different directions.
Post-run analysis you could use AUDITing or tracing to see what tables were affected.
There are several different ways you can get some or all of this information, but I can't think of any method that will give you the information in the exact format you specified.
Tracing
A trace file can record everything, but it's all stored in a text file meant to be read by a human. There are lots of examples for how to do this, here's one that just worked for me: http://tonguc.wordpress.com/2006/12/30/introduction-to-oracle-trace-utulity-and-understanding-the-fundamental-performance-equation/
Profiling
You can use DBMS_PROFILER to record which line numbers are called by the procedure. Then you'd have to join the line numbers to DBA_SOURCE to get the actual commands.
V$SQL
This records SQL statements executed. You could search for SQL by PARSING_SCHEMA_NAME and order by LAST_UPDATE_TIME. But this won't get the PL/SQL, and V$SQL can be difficult to use. (SQL may age out, or could get loaded by someone else, etc.)
But to get exactly what you want, all of these solutions require you to write a program to parse SQL and PL/SQL. I'm sure there are tools to do this, but I have no experience with them.
You can always write your own custom logging, but that's a huge amount of work. The best solution may be to ask the developers to adequately document every function, and list the purpose, inputs, outputs, and side-effects of all their code.
In MySql you can get information on the tables that are being affected by adding the keyword EXPLAIN in the start of your Query. It will give you different information's listed as columns. Check if there is a feature like this in Oracle might help in your scenario.

Resources