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%';
Related
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.
I have a database with (too) many triggers. They can cascade.
I have a query, which seems simple, and by no means I can remember the effect of all triggers. So, that simple query might actually be not simple at all and not do what I expect.
Is there a way to know what triggers would fire before running the query, or what triggers have fired after running it (not committed yet)?
I am not really interested in queries like SELECT … FROM user_triggers WHERE … because I know them already, and also because it does not tell me whether the firing conditions of the triggers will be met in my query.
Thanks
"I have a database with (too) many triggers. They can cascade."
This is just one of the reasons why many people anathematize triggers.
"Is there a way to know what triggers would fire before running the
query"
No. Let's consider something which you might find in an UPDATE trigger body:
if :new.sal > :old.sal * 1.2 then
insert into big_pay_rises values (:new.empno, :old.sal, :new.sal, sysdate);
end if;
How could we tell whether the trigger on BIG_PAY_RISES will fire? It might, it might not depending on an algorithm we cannot parse out of the DML statement.
So, the best you can hope for is a recursive search of DBA_TRIGGERS and DBA_DEPENDENCIES to identify all the triggers which might feature in your cascade. But it's going to be impossible to identify which ones will definitely fire in any given scenario.
" or what triggers have fired after running it (not committed yet)?"
As others have pointed out, logging is one option. But if you are using Oracle 11g you have another option: the PL/SQL Hierarchical Profiler. This is a non-intrusive tool which tracks all the PL/SQL program units touched by a PL/SQL call, including triggers. One of the cool features of the Hierarchical Profiler is that it includes PUs which belong in other schemas, which might be useful with cascading triggers.
So, you just need to wrap your SQL in an anonymous block and call it with the Hierarchical Profiler. Then you can filter you report to reveal only the triggers which fired. Find out more .
Is there a way to know what triggers would fire before running the query, or what triggers have fired after running it (not committed yet)?
To address this I would run the query inside an anonymous block using a PL/SQL debugger.
There is no such thing called parse through your query and give u the triggers involved in your query. It is going to be as simple as this. Just pick the table names from the query you are running and for each one just list the triggers using the following query before running the query. Isn't that simple enough?
select trigger_name
, trigger_type
, status
from dba_triggers
where owner = '&owner'
and table_name = '&table'
order by status, trigger_name
I am using Oracle 11g and Toad for Oracle. How can I display execution plan for queries?
In Sql server management studio execution plan can be displayed as graphical format. Is there any functionality/tool like that on Toad for oracle?
CTRL-E
Make sure you've ended the query with a semi-colon (and the query above)
Edit:
You need to set-up the TOAD plan table for use. If you think it's already setup on your DB then you may just need to be granted access. Alternatively in my slightly older version of TOAD it's under:
Database --> Administer --> Server Side Objects Wizard. From here you can create the plan table(s) in a schema that you choose.
You should create the PLAN_TABLE using a script provided by Oracle
which is named UTLXPLAN.SQL and is located in one of the installation folders
on the database server.
Then, you should use the EXPLAIN PLAN statement for generating a plan for a SQL statement, like this:
EXPLAIN PLAN SET STATEMENT_ID = 'your_identifier_for_this_plan'
FOR
... your statement ... ;
Then, you can use either a select from PLAN_TABLE (usually using a hierarchical query) or the DBMS_XPLAN.DISPLAY_PLAN procedure to display the plan.
In the same folder where the UTLXPLAN.SQL file is located, there usually exist
examples of using this procedure.
Also, in SQL*PLUS you can use the SET AUTOTRACE feature.
For TOAD FOR ORACLE
this helped me How do I view the Explain Plan in Oracle Sql developer?, I just write what they did in sql developer and wrote in the toad editor and then execute.
Example
explain plan for select field1, field2 from TABLE_NAME;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
Check that all queries end with a semicolon, put the cursor on the query you want to analyze and hit CTRL-E.
The first time you could get a popup that asks for the name of the plan table, it suggests TOAD_PLAN_TABLE but it's better to use the standard Oracle table PLAN_TABLE that should be already available. So enter PLAN_TABLE in place of TOAD_PLAN_TABLE (do not specify a schema) and hit OK. You should get a message saying that the object already exists: hit OK again to acknowledge it. Now try CTRL-E again and you'll get the explain plan.
To view/change the currently configured plan table name go to menu "View / Toad Options / Oracle General".
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.
Can I find out when the last INSERT, UPDATE or DELETE statement was performed on a table in an Oracle database and if so, how?
A little background: The Oracle version is 10g. I have a batch application that runs regularly, reads data from a single Oracle table and writes it into a file. I would like to skip this if the data hasn't changed since the last time the job ran.
The application is written in C++ and communicates with Oracle via OCI. It logs into Oracle with a "normal" user, so I can't use any special admin stuff.
Edit: Okay, "Special Admin Stuff" wasn't exactly a good description. What I mean is: I can't do anything besides SELECTing from tables and calling stored procedures. Changing anything about the database itself (like adding triggers), is sadly not an option if want to get it done before 2010.
I'm really late to this party but here's how I did it:
SELECT SCN_TO_TIMESTAMP(MAX(ora_rowscn)) from myTable;
It's close enough for my purposes.
Since you are on 10g, you could potentially use the ORA_ROWSCN pseudocolumn. That gives you an upper bound of the last SCN (system change number) that caused a change in the row. Since this is an increasing sequence, you could store off the maximum ORA_ROWSCN that you've seen and then look only for data with an SCN greater than that.
By default, ORA_ROWSCN is actually maintained at the block level, so a change to any row in a block will change the ORA_ROWSCN for all rows in the block. This is probably quite sufficient if the intention is to minimize the number of rows you process multiple times with no changes if we're talking about "normal" data access patterns. You can rebuild the table with ROWDEPENDENCIES which will cause the ORA_ROWSCN to be tracked at the row level, which gives you more granular information but requires a one-time effort to rebuild the table.
Another option would be to configure something like Change Data Capture (CDC) and to make your OCI application a subscriber to changes to the table, but that also requires a one-time effort to configure CDC.
Ask your DBA about auditing. He can start an audit with a simple command like :
AUDIT INSERT ON user.table
Then you can query the table USER_AUDIT_OBJECT to determine if there has been an insert on your table since the last export.
google for Oracle auditing for more info...
SELECT * FROM all_tab_modifications;
Could you run a checksum of some sort on the result and store that locally? Then when your application queries the database, you can compare its checksum and determine if you should import it?
It looks like you may be able to use the ORA_HASH function to accomplish this.
Update: Another good resource: 10g’s ORA_HASH function to determine if two Oracle tables’ data are equal
Oracle can watch tables for changes and when a change occurs can execute a callback function in PL/SQL or OCI. The callback gets an object that's a collection of tables which changed, and that has a collection of rowid which changed, and the type of action, Ins, upd, del.
So you don't even go to the table, you sit and wait to be called. You'll only go if there are changes to write.
It's called Database Change Notification. It's much simpler than CDC as Justin mentioned, but both require some fancy admin stuff. The good part is that neither of these require changes to the APPLICATION.
The caveat is that CDC is fine for high volume tables, DCN is not.
If the auditing is enabled on the server, just simply use
SELECT *
FROM ALL_TAB_MODIFICATIONS
WHERE TABLE_NAME IN ()
You would need to add a trigger on insert, update, delete that sets a value in another table to sysdate.
When you run application, it would read the value and save it somewhere so that the next time it is run it has a reference to compare.
Would you consider that "Special Admin Stuff"?
It would be better to describe what you're actually doing so you get clearer answers.
How long does the batch process take to write the file? It may be easiest to let it go ahead and then compare the file against a copy of the file from the previous run to see if they are identical.
If any one is still looking for an answer they can use Oracle Database Change Notification feature coming with Oracle 10g. It requires CHANGE NOTIFICATION system privilege. You can register listeners when to trigger a notification back to the application.
Please use the below statement
select * from all_objects ao where ao.OBJECT_TYPE = 'TABLE' and ao.OWNER = 'YOUR_SCHEMA_NAME'