Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Sudhir.

Asked: September 08, 2001 - 10:35 am UTC

Last updated: August 30, 2006 - 8:10 am UTC

Version: 8.1.7.2

Viewed 1000+ times

You Asked

Hello Tom! Hope your vacation was great. Also, thanks for your response on my prior question.

This is my new question: In our application a user may update/insert/delete row(s) from many tables. If we want to replay the user action we need to trap the user transactions. One other problem is all the users have their own id but backend server which does work for them always logs into db with the same userid. Thus using LogMiner etc very difficult. Also I dont have any say in asking for code change to reflect such information. Mainly if this can be done on database non-intrusively then it is great.

I was thining along following lines
1) create a sequence to be used as transaction number (unless there is such thing as a transaction number accessible in trigger)
2) use a global temporary table.
3) Put triggers on each table such that each checks if a row exists in global temp. table. If one exists then you know some other trigger fired before you and you are either in the middle of transaction or at the end of one. If no row exists then insert sequence number in it and use it in "4" below.
4) Of course after every trigger fire, we will save all table row information and transaction number and sysdate in txn_info table.
5) at the end of transaction the row in global temp will be gone unless it has some use

So I should have a trail table like below

TXN# TABLE_NAME ACTION TXN_DATE OLD_VAL NEW_VAL
1 CUST Delete 09/08/2001 12:12:30 some some
2 CUST_ADDR Delete 09/08/2001 12:12:35 some some
1 CUST_ADDR Update 09/08/2001 12:12:36 some some
2 ACCT_INFO Add 09/08/2001 12:12:36 some some
...

etc

So now if I say
select TXN#, TABLE_NAME, ACTION from tran_info
order by txn#, txn_date

i should get all the transactions.

Do you think this will work or is there any better way? Mind you I have really not developed any complex triggers or such application.

thanks for sea of information you provide.

Sudhir


and Tom said...

Well, you could use our transaction id instead (less work on your part, less triggers and you could tie this into logminer after the fact). A simple select would get it for you. You might consider having your DBA create a view that replaces the query below and granting you select on that view (so you don't need select on sys.v_$transaction, v_$session and v_$mystat, just the view).



ops$tkyte@ORA8I.WORLD> create table t ( x int );
Table created.

ops$tkyte@ORA8I.WORLD> create or replace trigger t_trigger
2 after insert or update or delete on t
3 for each row
4 declare
5 l_transaction_id varchar2(75);
6 begin
7 select xidusn || '.' || xidslot || '.' || xidsqn
8 into l_transaction_id
9 from v$transaction
10 where addr = ( select taddr
11 from v$session
12 where sid = ( select sid
13 from v$mystat
14 where rownum = 1 )
15 );
16
17 dbms_output.put_line( l_transaction_id );
18 end;
19 /
Trigger created.

ops$tkyte@ORA8I.WORLD> insert into t values ( 1 );
28.48.74514

1 row created.

ops$tkyte@ORA8I.WORLD> insert into t values ( 2 );
28.48.74514

1 row created.

ops$tkyte@ORA8I.WORLD> commit;
Commit complete.

ops$tkyte@ORA8I.WORLD> insert into t values ( 3 );
29.64.74394

1 row created.





Rating

  (6 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

very good information

A reader, September 08, 2001 - 7:34 pm UTC

I thank you for the information. I will play with it.
Tom you are the best and the most humble person I have ever met.

thanks again!

Sudhir

See Tom's more recent transaction_id recommendation

Duke Ganote, March 28, 2004 - 9:44 pm UTC

I found the query doesn't always seem to reliably provide a transaction_id (at least in my hands). However, Tom's response to a later question "Locking and Cocurrency in 9i.", found at </code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:8913646338893,
recommends using the DBMS_TRANSACTION package, which even in my hands appeared reliable.  

Interestingly, combining a transaction_id with the 9i flashback's get SCN function or 8i's COMMITSCN feature (see 
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:2591957673673#2592288690458 <code>for both) and it appears one could construct a Do-It-Yourself (DIY) replication.

Tom Kyte
March 29, 2004 - 7:13 am UTC

how could this query not "reliably" provide a transaction_id?

You have a session (so the v$session query works)

and if the trigger fires you have a v$transaction entry for sure.

so, i'd be at a loss to understand the circumstances whereby this won't work. do you have some sort of details for this?


You'd need to use the commitscn (that is what our replication uses) in order to get the proper ORDERING of transactions. (but if you DIY replicate, you've totally missed the point of purchased software.......)

DIY Fat-fingering

Duke Ganote, March 29, 2004 - 1:43 pm UTC

Tom-- I'll have to embarass myself by admitting I'm unable to reproduce the results after a full night's sleep...perhaps I butter-fingered the sys view I created for the query. I'll attribute the erratic results to being too fatigued that night! Apologies. Certainly, frustration led me to scour your site further and find your DBMS_TRANSACTION.LOCAL_TRANSACTION_ID recommendation, which even I couldn't foul up despite fatigue.

As for "why" I was experimenting with DIY replication: it primarily self-educational while reading your "Expert 1-on-1 Oracle" appendix on log miner, but partly (1) because our corporate standard for data transport is a non-Oracle product, (2) the goal is "low latency" or "real time" replication, and (3) we're on 8.1.7.4 for a while yet. Thus, I was exploring means to pushing granular changes to a central data store. I'm a big fan of not re-inventing the wheel; I assume 9i's Change Data Capture (CDC), apparently based on log miner, will provide this functionality, which I was reading about in Oracle magazine's Nov/Dec 2003 issue.

Thank you!

Another option: Use 9*i "Change Data Capture"

Shimon Tourgeman., January 18, 2005 - 7:58 am UTC

For details see: chapter 15 of "Oracle9 i Data Warehousing Guide".

this nice feature is based on a Publish&Subscribe model which will catpture aby DML action against any table that your are subscribed to, and let you access a change table using a supplied DBMS packages.

Worth trying, I think...I like this feature. its revolutional.

Shimon.


A Reader, August 25, 2006 - 8:51 am UTC

I have a table called "stat". Data gets inserted into this table by another procedure. When step_no=7 and task_no=0, status='READY',the insert stops. Can you please explain me if I can capture, the data that is being inserted to stat table, into a collection instead of oracle table and output using dbms_output.put_line?

Thnaks

create table stat
(id number
,step_no number
,task_no number
,status varchar2(10)
,count number
);

insert into stat
values
(1000,5,1,'OK',20);


insert into stat
values
(1000,5,2,'ERROR',50);

insert into stat
values
(1000,5,2,'OK',20);


insert into stat
values
(1000,5,3,'OK',20);


insert into stat
values
(1000,5,4,'OK',20);


insert into stat
values
(1000,7,0,'READY',20);






Tom Kyte
August 27, 2006 - 8:22 pm UTC

this is a strange one.

can you - yes, we could.

I won't tell you how until you tell me why? what is going to happen to this other data, what will display it? (dbms_output.put_line is pretty much a sqlplus thing unless your CLIENT application calls dbms_output.get_lines and displays it).

need more info, what is the goal here, can you explain this a little better?

A reader, August 29, 2006 - 11:18 pm UTC

Data gets inserted into stat table and it changes.
First it may be in
5,1,'OK',20.
It will then get changed to
5,1,'READY' 15
5,1,'ERROR',5.

I want to capture everything 5,1,'OK',20; 5,1,'READY',15 and 5,1,'ERROR',5.

I was wondering if I can capture into a collection and display it as and when data gets changed.





Tom Kyte
August 30, 2006 - 8:10 am UTC

this still isn't really making sense here. sorry - I don't think we'll be able to do this one.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library