amazing feature
Ofir Manor, August 31, 2004 - 3:01 pm UTC
If I had a nickel for every time a saw a project manually implementing that feature!
This is a great feature. Are there any limitation about it's usage, like no support for IOT, partitioning, UTF8, etc?
August 31, 2004 - 3:30 pm UTC
well, i've discovered that rowdependencies while supported with IOTs, isn't working properly with ora_rowscn - filed a bug on that.
but there are no documented restrictions, no.
how?
Dave, August 31, 2004 - 7:00 pm UTC
bit OT, but im curious as to how you learn the new features and then learn how to use / implement them.
I know you will have read the docs and seen all the new features, how do you go about practising with them - finding an application for them.
Is there internal oracle training on the 'cool' stuff or simple you self learn everything you can?
Really interested in your methods for applying new technology
September 01, 2004 - 7:34 am UTC
self study...
continuing to write code for money (meaning, it is not all esoteric "cool feature", it is "i've got things that need to function day in day out...")
talking with others or just listening in to what they say.... (this is big, huge, really large)
reading questions and thinking of possible solutions, seeing others answers (this is how it all started for me in 1994, on the usenet newsgroups)......
Excellent description.
Matt, August 31, 2004 - 7:23 pm UTC
That was a great explaination.
Some additional questions:
1) Physically how is the block level scn data stored in the block header? In the block header?
2) What about the rows level scn data? again, in the block header?
3) What is the overhead if tracking rowdependencies on a table. I presume there is extra space needed on the block, and some processing overhead. Is this processing overhead measurable?
Many Thanks.
September 01, 2004 - 7:44 am UTC
1) it is information in the block header, yes.
2) 6 bytes/row, at the row level.
3) does take extra space, but i've not measured any significant overhead processing wise (cpu or otherwise)
Alessandro Nazzani, November 01, 2004 - 6:34 am UTC
Hi Tom.
I'm experimenting this technique (ORA_ROWSCN) with a simple update web form:
1) load record #1 in my form
2) go to sql-plus, manually update record #1 and commit
3) hit the submit button in the browser and receive the expected error message
So far, so good. But:
1) load record #1 in my form
2) go to sql-plus, manually update record #1
3) hit the submit button in the browser (session hangs)
4) commit the update in sql-plus
5) in the browser I get the "update was successful" message (and record #1 actually contains data changed in the form)
Is this the expected behaviour or am I doing something wrong?
Alessandro
November 01, 2004 - 1:24 pm UTC
show us the update code you are using?
To Alessandro
A reader, November 01, 2004 - 1:44 pm UTC
Are you creating the underlying tables with rowdependencies option? You have to do that for using
ora_rowscn for optimistic locking.
Just checking:)
November 02, 2004 - 6:32 am UTC
well, only partially true. the ora_rowscn is tracked at the "block level" by default so you would get "false -- sorry row was updated" messages if you didn't enable row dependencies-- which is the opposite of what he is saying above.
I can't understand...
Zhur, November 01, 2004 - 3:19 pm UTC
How Oracle do it?
Let's suppose that we have a long transaction. So long, that after some time Oracle starts write blocks from the buffer to disk.
But we will know SCN only after commit (am I right?), so we must update all blocks again... Great overhead, I think.
Sorry for my english...
November 02, 2004 - 6:36 am UTC
no, doesn't work that way. it doesn't go out and update all of the blocks, that would be fairly inefficient.
Alessandro Nazzani, November 02, 2004 - 5:26 am UTC
> show us the update code you are using?
procedure update_notizia (p_old_scn in number,
p_old_rowid in rowid,
p_inevidenza in varchar2,
p_titolo in varchar2,
p_abstract in varchar2,
p_notizia in varchar2,
p_file in varchar2 DEFAULT NULL,
p_id_sezione in number,
P_ABSTRACT_MAXCHARS in number,
P_NOTIZIA_MAXCHARS in number
) as
l_id_upload PM_NEWS_FILES.ID_UPLOAD%TYPE DEFAULT NULL;
BEGIN
If (p_file is not null) Then
select PM_NEWS_FILES.ID_UPLOAD into l_id_upload from PM_NEWS_FILES where PM_NEWS_FILES.NAME=p_file;
End If;
update PM_NEWS_NOTIZIE set inevidenza = p_inevidenza,
titolo = p_titolo,
abstract = p_abstract,
testo = p_notizia,
id_upload = l_id_upload
where rowid = p_old_id_notizia and
ora_rowscn = p_old_scn;
If (SQL%rowcount = 0) Then
htp.bold('Sorry, record was modified, try again.<br>' );
pm_news_forms.p_notizia (p_old_id_notizia);
Else
htp.bold( 'Ok, update successful (ID ' || htf.escape_sc(p_old_id_notizia) || ').<br>');
End If;
END;
And yes, I have (re)created the table with rowdependencies.
Thanks all for your assistance.
Alessandro
November 02, 2004 - 8:23 am UTC
I cannot reproduce your issue -- what do you get if you run this test script and have you considered putting out some debug information from your procedure (eg: before you update, select out and print the row you are planning on updating to see what it looks like?)
ops$tkyte@ORA10G> drop table t;
Table dropped.
ops$tkyte@ORA10G> create table t as select * from scott.emp;
Table created.
ops$tkyte@ORA10G> column rowid new_val rid
ops$tkyte@ORA10G> column rowscn new_val rscn
ops$tkyte@ORA10G> select rowid, ora_rowscn rowscn, ename, sal from emp where ename = 'KING';
ROWID ROWSCN ENAME SAL
------------------ ---------- ---------- ----------
AAAMuKAAEAAAAPMAAI 27321452 KING 605
ops$tkyte@ORA10G> declare
2 pragma autonomous_transaction;
3 begin
4 update emp set sal = sal*1.1 where ename = 'KING';
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
ops$tkyte@ORA10G> update emp set sal = 100 where rowid = '&RID' and ora_rowscn = &RSCN;
old 1: update emp set sal = 100 where rowid = '&RID' and ora_rowscn = &RSCN
new 1: update emp set sal = 100 where rowid = 'AAAMuKAAEAAAAPMAAI' and ora_rowscn = 27321452
0 rows updated.
ops$tkyte@ORA10G> select rowid, ora_rowscn rowscn, ename, sal from emp where ename = 'KING';
ROWID ROWSCN ENAME SAL
------------------ ---------- ---------- ----------
AAAMuKAAEAAAAPMAAI 27321472 KING 665.5
Alessandro Nazzani, November 02, 2004 - 5:35 am UTC
Sorry for the typo: p_old_id_notizia is actually p_old_rowid.
procedure update_notizia (p_old_scn in number,
p_old_rowid in rowid,
p_inevidenza in varchar2,
p_titolo in varchar2,
p_abstract in varchar2,
p_notizia in varchar2,
p_file in varchar2 DEFAULT NULL,
p_id_sezione in number,
P_ABSTRACT_MAXCHARS in number,
P_NOTIZIA_MAXCHARS in number
) as
l_id_upload PM_NEWS_FILES.ID_UPLOAD%TYPE DEFAULT NULL;
BEGIN
If (p_file is not null) Then
select PM_NEWS_FILES.ID_UPLOAD into l_id_upload from PM_NEWS_FILES where PM_NEWS_FILES.NAME=p_file;
End If;
update PM_NEWS_NOTIZIE set inevidenza = p_inevidenza,
titolo = p_titolo,
abstract = p_abstract,
testo = p_notizia,
id_upload = l_id_upload
where rowid = p_old_rowid and
ora_rowscn = p_old_scn;
If (SQL%rowcount = 0) Then
htp.bold('Sorry, record was modified, try again.<br>' );
pm_news_forms.p_notizia (p_old_rowid);
Else
htp.bold( 'Ok, update successful (ID ' || htf.escape_sc(p_old_rowid) || ').<br>');
End If;
END;
Alessandro Nazzani, November 02, 2004 - 9:06 am UTC
I can't reproduce: don't know what I have changed in the last 24 hrs but now it works (browser session does not hang and I get the "already updated" error which, I suppose, is the expected behaviour).
Really sorry for wasting your precious time.
Alessandro
ORA_ROWSCN to add security
Mark Wooldridge, November 02, 2004 - 2:31 pm UTC
This locking strategy used in a web base environment or any type of implementation where the client values being passed to the application could be modified by a malicious client (or an application that contained bugs that generated incorrect ID's) user would provide an additional level of security.
Obviously there should be access control checks such as VPD or procedural code to provide security. This would just add to the security.
The malicious user would need more than just a few ID's to try to attack the application to update information. They would need the ability to get the SCN correct also. This would required read or execute access to the parts of the application that generate the SCN values or guess them correctly. The big key is that when other legitimate users update the values the SCN's would change thus making the value the malicious user needs dynamic.
Given the SCN can be converted to time, could the value be more easily guessed?
November 03, 2004 - 6:29 am UTC
but they need to know the ora_rowscn of the row they wanted to update -- NOT the "next scn to be seen in the system"
they need to have queried up the record -- in order to see the rowscn for that record.
so, not sure I agree with your conclusion on this one. seeing what ora_rowscns are being produced won't help me guess the ora rowscn of the 'KING' record.
Added security
Mark Wooldridge, November 05, 2004 - 12:39 pm UTC
The added security would come from the fact that a user may not be able to query up the content but may have guessed the ID's of the record but would have difficulty in guessing the ora_rowscn of the data. In the case where I can query the content but not modify it I would hope the application is smart enough to not bring back the ora_rowscn.
For example the application has a screen to manage names and I know I can see/update names 50, 55, and 60. There is a good chance there are names 49, 51-54, etc. In addtion to the current security of the application not knowing the ora_rowscn of 49 would be that much more difficult to use the application to update name 49.
Not that I would rely on this for security it just adds to the overall security.
Flaw in use of ora_rowscn for optimistic locking?
Andrew Mannering, August 17, 2005 - 7:01 am UTC
My developers have been trying to use ora_rowscn to implement optimistic locking, and have found what appears to be a flaw in it's use.
The ora_rowscn is nulled for a row as soon as the row is modified, and is only repopulated on commit or rollback, so it is impossible to use a RETURNING clause or to re-read the rowscn from within a transaction. Potentially, in a high contention table, the row could be updated by other processes between the time the commit is done and the rowscn is reread by the original process.
SQL> create table t (tid number, tchar varchar2(10))
2 rowdependencies
3 /
Table created
SQL> insert into t (tid, tchar) values (1, 'Test')
2 /
1 row inserted
SQL> commit
2 /
Commit complete
SQL> select t.tid, t.tchar, ora_rowscn from t
2 /
TID TCHAR ORA_ROWSCN
---------- ---------- ----------
1 Test 4636918058
SQL> update t set t.tchar = 'Changed' where t.tid = 1
2 /
1 row updated
[Now in another session update the same row to 'Stomped' - this second session will be blocked by the update from this session]
SQL> select t.tid, t.tchar, ora_rowscn from t
2 /
TID TCHAR ORA_ROWSCN
---------- ---------- ----------
1 Changed
[Note the ora_rowscn is null, so we can't save the value yet]
SQL> commit
2 /
Commit complete
[The second session also commits now...]
SQL> select t.tid, t.tchar, t.ora_rowscn from t
2 /
TID TCHAR ORA_ROWSCN
---------- ---------- ----------
1 Stomped 4636918190
SQL>
If the app only rereads the ora_rowscn, it may now have the right SCN, but the wrong data. Rereading the rest of the row has downsides as it could mean reloading a lot more besides - the application is n-tier and so stores a lot of state information in the middle tier.
Given this limititation, they've gone back to using triggers and an incremented number column for optimistic locking.
From what I can glean from the documentation this is not unexpected behaviour, but it does mean it's use for optimistic locking is more limited than first appears (unless this behaviour is a bug!).
Server version is 10.1.0.3 EE on Solaris.
August 17, 2005 - 1:40 pm UTC
If the app only rereads the ora_rowscn
therein lies your mistake, it cannot just re-read the ora_rowscn. the DATA HAS CHANGED, IT WILL BE DIFFERENT on the re-read! period.
How could you NOT re-read it?
You are reading data some other session is in the process of modifying, it will be DIFFERENT after they commit.
I don't see what you could use the data you read out (with the null rowscn) for! Your loser (sorry, meant user) will LOSE when they go to update it by definition!
Followup to Andrew Mannering
Gary, August 17, 2005 - 9:09 pm UTC
"The ora_rowscn is nulled for a row as soon as the row is modified, and is only repopulated on commit or rollback, so it is impossible to use a RETURNING clause or to re-read the rowscn from within a transaction."
Until you commit the update, the row is locked as yours. Whenever you see a NULL ORA_ROWSCN, then that row must contain your uncommitted change (as any other session would show a committed change that has an ORA_ROWSCN).
I think you need to look at your transaction boundaries too.
You should not have an
INSERT ..
COMMIT;
UPDATE ...
COMMIT;
You either need a
INSERT...
UPDATE...
COMMIT;
or
INSERT ...
COMMIT;
SELECT ...
UPDATE ...
COMMIT;
Once you've committed, that row is up for grabs and you have to re-read it before updating it so that you know what you are updating.
Finally, your updates didn't include the check on ORA_ROWSCN. If they had, the update to STOMPED would have failed (zero rows updated), as it would have still had the ORA_ROWSCN from 'Test' and so would not have updated the 'Changed' row.
Some Suprises were in Store for Me with SCN Number
Prasanth Kumar, February 01, 2006 - 6:25 am UTC
Hi Tom,
I have been Following your Site for quite a Long Time. Your Site is I guess Great for any New Database Programmer. Now i am very new to Databases so forgive me if My question is Foolish.
I was actually Looking to Implement Optimistic Locking. And I guess i have finally found the Solution. Now i have found something Funny with SCN.
I had Fired an Update Command in a Oracle Table. only 2 rows were affected but the SCN Number changed for some 6 Rows.
Any Guesses Why???
M i Missing Something...
February 02, 2006 - 3:44 am UTC
I presume you are refering to ora_rowscn? If so, here is an excerpt from my most recent book on that:
<quote src=Expert Oracle: Database Architecture>
Optimistic Locking Using ORA_ROWSCN
Starting with Oracle 10g Release 1, you have the option to use the built-in ORA_ROWSCN function. It works very much like the version column technique described previously, but it can be performed automatically by Oracleyou need no extra column in the table and no extra update/maintenance code to update this value.
ORA_ROWSCN is based on the internal Oracle system clock, the SCN. Every time you commit in Oracle, the SCN advances (other things can advance it as well, but it only advances; it never goes back). The concept is identical to the previous methods in that you retrieve ORA_ROWSCN upon data retrieval, and you verify it has not changed when you go to update. The only reason I give it more than passing mention is that unless you created the table to support the maintenance of ORA_ROWSCN at the row level, it is maintained at the block level. That is, by default many rows on a single block will share the same ORA_ROWSCN value. If you update a row on a block with 50 other rows, then they will all have their ORA_ROWSCN advanced as well. This would almost certainly lead to many false positives, whereby you believe a row was modified that in fact was not.
Therefore, you need to be aware of this fact and understand how to change the behavior.
To see the behavior and then change it, well use the small DEPT table again:
ops$tkyte@ORA10G> create table dept
2 (deptno, dname, loc, data,
3 constraint dept_pk primary key(deptno)
4 )
5 as
6 select deptno, dname, loc, rpad('*',3500,'*')
7 from scott.dept;
Table created.
Now we can inspect what block each row is on (it is safe to assume in this case they are in the same file, so a common block number indicates they are on the same block). I was using an 8KB block size with a row width of about 3,550 bytes, so I am expecting there to be two rows per block for this example:
ops$tkyte@ORA10G> select deptno, dname,
2 dbms_rowid.rowid_block_number(rowid) blockno,
3 ora_rowscn
4 from dept;
DEPTNO DNAME BLOCKNO ORA_ROWSCN
---------- -------------- ---------- ----------
10 ACCOUNTING 20972 34676029
20 RESEARCH 20972 34676029
30 SALES 20973 34676029
40 OPERATIONS 20973 34676029
And sure enough, that is what we observe in this case. So, lets update the row where DEPTNO = 10 on block 20972:
ops$tkyte@ORA10G> update dept
2 set dname = lower(dname)
3 where deptno = 10;
1 row updated.
ops$tkyte@ORA10G> commit;
Commit complete.
What well observe next shows the consequences of ORA_ROWSCN being tracked at the block level. We modified and committed the changes to a single row, but the ORA_ROWSCN values of both of the rows on block 20972 have been advanced:
ops$tkyte@ORA10G> select deptno, dname,
2 dbms_rowid.rowid_block_number(rowid) blockno,
3 ora_rowscn
4 from dept;
DEPTNO DNAME BLOCKNO ORA_ROWSCN
---------- -------------- ---------- ----------
10 accounting 20972 34676046
20 RESEARCH 20972 34676046
30 SALES 20973 34676029
40 OPERATIONS 20973 34676029
It would appear to anyone else that had read the DEPTNO=20 row that it had been modified, even though it was not. The rows on block 20973 are safewe didnt modify them, so they did not advance. However, if we were to update either of them, both would advance. So the question becomes how to modify this default behavior. Well, unfortunately, we have to re-create the segment with ROWDEPENDENCIES enabled.
Row dependency tracking was added to the database with Oracle9i in support of advanced replication, to allow for better parallel propagation of changes. Prior to Oracle 10g, its only use was in a replication environment, but starting in Oracle 10g we can use it to implement an effective optimistic locking technique with ORA_ROWSCN. It will add 6 bytes of overhead to each row (so it is not a space saver compared to the do-it-yourself version column) and that is, in fact, why it requires a table re-create and not just a simple ALTER TABLE: the physical block structure must be changed to accommodate this feature.
Lets rebuild our table to enable ROWDEPENDENCIES. We could use the online rebuild capabilities in DBMS_REDEFINITION (another supplied package) to do this, but for something so small, well just start over:
ops$tkyte@ORA10G> drop table dept;
Table dropped.
ops$tkyte@ORA10G> create table dept
2 (deptno, dname, loc, data,
3 constraint dept_pk primary key(deptno)
4 )
5 ROWDEPENDENCIES
6 as
7 select deptno, dname, loc, rpad('*',3500,'*')
8 from scott.dept;
Table created.
ops$tkyte@ORA10G> select deptno, dname,
2 dbms_rowid.rowid_block_number(rowid) blockno,
3 ora_rowscn
4 from dept;
DEPTNO DNAME BLOCKNO ORA_ROWSCN
---------- -------------- ---------- ----------
10 ACCOUNTING 21020 34676364
20 RESEARCH 21020 34676364
30 SALES 21021 34676364
40 OPERATIONS 21021 34676364
Were back where we were before: four rows on two blocks, all having the same initial ORA_ROWSCN value. Now when we update DEPTNO=10
ops$tkyte@ORA10G> update dept
2 set dname = lower(dname)
3 where deptno = 10;
1 row updated.
ops$tkyte@ORA10G> commit;
Commit complete.
we should observe the following upon querying the DEPT table:
ops$tkyte@ORA10G> select deptno, dname,
2 dbms_rowid.rowid_block_number(rowid) blockno,
3 ora_rowscn
4 from dept;
DEPTNO DNAME BLOCKNO ORA_ROWSCN
---------- -------------- ---------- ----------
10 accounting 21020 34676381
20 RESEARCH 21020 34676364
30 SALES 21021 34676364
40 OPERATIONS 21021 34676364
The only modified ORA_ROWSCN at this point belongs to DEPTNO = 10, exactly what we wanted. We can now rely on ORA_ROWSCN to detect row-level changes for us.
</quote>
Followup to My Previous Mail..
Prasanth Kumar, February 01, 2006 - 6:33 am UTC
When i do select distinct(ORA_ROWSCN) from tablename it fetches me only 2 RowSCn Number. So is it possible that one SCN NUmber is mapping to many Rows.???????
February 02, 2006 - 3:44 am UTC
see above
ORA_ROWSCN Level of Accuracy
Prasanth Kumar, February 06, 2006 - 2:36 am UTC
Hi Tom,
Thankz a lot for the previous Reply. It was Most Useful. I have just One more small Querry. What is the level of Precission of ORA_ROWSCN. Like i have Heared that TimeStamping dosn't Work Well if 2 transactions are update a row within a timestamp of 16ms. Does this Hold for ORA_ROWSCN also. Will this Number advance for every Transaction.?????
February 07, 2006 - 12:31 am UTC
But the flaw with the timestamp 'argument' is - this is for optimistic concurrency control for human interactions. In the time it takes to
a) read out the data
b) format the html page
c) send it to the browser
d) let a human read and interact with it
e) send it back
you are talking seconds, not tenths of seconds, not centiseconds, not milliseconds.
ora_rowscn will advance for each transaction - as would the timestamp in practicality.
ORA_ROWSCN bug with VPD
Massimo Galavotti, February 07, 2006 - 3:12 am UTC
ORA_ROWSCN ??.
Is fine but there is a bug.If a table has a vpd policy and the policy return a where clause oracle trigger an error.
Whe have found this bug.
The bug number is 4947170
Massimo
February 07, 2006 - 5:36 am UTC
I see that - I don't like their workaround (doesn't work for any query that returns more than one row). However, a view can correct this:
ops$tkyte@ORA10GR2> create or replace function my_security_function( p_schema in varchar2,
2 p_object in varchar2 ) return varchar2
3 as
4 begin
5 return '1=1';
6 end;
7 /
Function created.
ops$tkyte@ORA10GR2> create table t ( x int );
Table created.
ops$tkyte@ORA10GR2> insert into t values ( 1 );
1 row created.
ops$tkyte@ORA10GR2> create or replace view v_of_t
2 as
3 select t.*, ora_rowscn rscn
4 from t;
View created.
ops$tkyte@ORA10GR2> begin
2 dbms_rls.add_policy
3 ( object_schema => user,
4 object_name => 'V_OF_T',
5 policy_name => 'MY_POLICY',
6 function_schema => user,
7 policy_function => 'My_Security_Function',
8 statement_types => 'select, insert, update, delete' ,
9 update_check => TRUE );
10 end;
11 /
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> select * from v_of_t;
X RSCN
---------- ----------
1 2207152
ORA_ROWSCN
Prasanth KUmar, February 10, 2006 - 3:04 am UTC
Hi Tom,
In Continuation to my previous Question. My Application is a Distributed Application. We can have many Concurent Users. Picture this Senario which is i Think a flaw in TimeStamping. Also i am using only Optimictic Locking.
User A Updates a Row. at Time X.
User B Reads the row
User C Updates the Row
Now if the update of User A and User C is within the 16ms Time Period- the Timestam dosn't Advance. So User B may well be doing a Dirty Read. So when user B want to update the row he will see that the Timestamp has not changed.
Is My understanding of Timestam Correct. If yes will this also happen if i use ORA_ROWSCN or do you prefer that i use a manually created version col. instead.
Regards
Prasanth
February 10, 2006 - 12:47 pm UTC
You are missing the logic. Add into your flow the READS of the row.
When user A read the row, user A would read the timestamp.
When user C read the row, user C would read the timestamp.
User C would not have been able to modify the row.
ORA_ROWSCN
Massimo Galavotti, February 12, 2006 - 8:59 am UTC
Hello Tom first thank for your job.I have tested your example and this works fine for me.But the Oracle manual at the chapter on the "ORA_ROWSCN Pseudocolumn" says "You cannot use this pseudocolumn in a query to a view".
So, you are my SQL hero but
Thank Massimo
February 12, 2006 - 11:37 am UTC
right, unless the VIEW exposes the ora_rowscn.
That is why it doesn't work straight out with VPD, VPD uses an inline view to rewrite out query - and then ora_rowscn isn't exposed. By explicitly exposing it - we work around that issue.
Null ORA_ROWSCN indicates uncomitted update?
John G. Galinski, March 29, 2006 - 3:43 pm UTC
I am new to Oracle and come to your web site for insight into how things really work in the world of Oracle. This thread has been fascinating but, what really caught my interest was what I learned when exploring Andrew Mannering's comments on ORA_ROWSCN being NULL. I executed the following and found that it was NULL not only for the session performing the "update" but, also for another session retreiving the data.
session1> create table t (tid number, tchar varchar2(10))
2 rowdependencies;
Table created.
session1> insert into t (tid, tchar) values (1, 'Test');
1 row created.
ilmsdb@ILMSDB.ROBUSTSYSTEMS.COM> commit;
Commit complete.
session1> select t.*,ora_rowscn from t;
TID TCHAR ORA_ROWSCN
---------- ---------- ----------
1 Test 40530552
session1> update t set t.tchar = 'Changed' where t.tid =;
1 row updated.
session1> select t.*,ora_rowscn from t;
TID TCHAR ORA_ROWSCN
---------- ---------- ----------
1 Changed
However from the second session:
session2> select t.*,ora_rowscn from t;
TID TCHAR ORA_ROWSCN
---------- ---------- ----------
1 Test
The second session sees the data as before the update was begun, which is what I expect from Oracle, but is also alerted to the fact that an uncomitted change is in process, by the NULL ORA_ROWSCN.
Im I right in my observations and can this ORA_ROWSCN behavior be used to improve the likely success of the optimistic locking strategy? For example, don't begin a transaction when any of the initial data is found to have NULL ORA_ROWSCNs.
March 29, 2006 - 7:11 pm UTC
well, a null is never equal to null so if you get null - you know you will NEVER be able to update the row in the end - the comparison just won't work.
bug 4103979 ?
Alberto Dell'Era, March 30, 2006 - 4:38 am UTC
John's test case doesn't reproduce in 10.2.0.1 :
session1> create table t (tid number, tchar varchar2(10)) rowdependencies;
Table created.
session1> insert into t (tid, tchar) values (1, 'Test');
1 row created.
session1> commit;
Commit complete.
session1> select t.*,ora_rowscn from t;
TID TCHAR ORA_ROWSCN
---------- ------------------------------ ----------
1 Test 153315161
session1> update t set t.tchar = 'Changed' where t.tid =1;
1 row updated.
session1> select t.*,ora_rowscn from t;
TID TCHAR ORA_ROWSCN
---------- ------------------------------ ----------
1 Changed *null*
session2> select t.*,ora_rowscn from t;
TID TCHAR ORA_ROWSCN
---------- ------------------------------ ----------
1 Test 153315161
John's behaviour seems consistent with bug 4103979, found in 10.1.0.3.0 and solved in 10.2.0.0. I was on Solaris 64bit, but it doesn't look like an operating system-dependent bug.
bug 4103979 ?
John G. Galinski, March 31, 2006 - 11:42 am UTC
Thanks Tom and Alberto for the followup. My version is 10.1.0.2.0, which makes my observations moot since the behavior will change when I update.
Problem with ORA_ROWSCN
Jonathan Lewis, June 17, 2006 - 5:09 am UTC
It looks like there's a bug with ORA_ROWSCN that makes it unsafe to use for optimistic locking. It doesn't appear to do the "write consistency" thing if two sessions try to update the same row with the same ora_rowscn, so you can end up with lost updates.
See bug 5270479
Table table re-creation, for ORA_ROWSCN
Tahir, July 05, 2006 - 3:49 am UTC
If I use the "ora_rowscn" in existing tables in production database. Which steps will be involved in populating data, constraints, indexes etc?
July 08, 2006 - 7:47 am UTC
all of them?
Not sure what you mean - if you want to use ora_rowscn AND you want it at the row level (not the block level), you would need to rebuild the table with "rowdependencies" (it is not a requirement, ora_rowscn can be useful at the block level for many cases).
You can use dbms_redefinition to do this online (search for that on this site for examples), in 10g - there is a copy_table_dependents routine that automates the copying of constraints and so on - in 9i, you are responsible for doing it.
Pending bug
Matthias, September 07, 2006 - 10:16 am UTC
Hello,
I encountered another pitfall with ora_rowscn.
It's not possible to use the ora_rowscn in a PLSQL insert statement like: "insert into table values rowdata returning ora_rowscn into variable;"
Sad but true.
Bug 5118104 is still pending.
September 07, 2006 - 12:00 pm UTC
but why would you need it? what is the use case here?
Pending Bug
Matthias, September 08, 2006 - 5:24 am UTC
Hello,
ok, as I understand the benefit of ora_rowscan is, that you can easily determine if a row has changed last read or not.
So whenever I do a DML on a particular row the ora_rowscn will change. Correct? (Don't bother about row and block issues.)
That means whenever I insert, update or delete a row I will check/read the ora_rowscan to be sure, that noone else has modified the row after my last read.
So the ora_rowscn is passed along with the rowdata to every function in my plsql application.
Its from my point of view exactly that behavior of ora_rowscan I use that the first sentence of your first answer was:"The real savings is that you don't need to SAVE the old values and then COMPARE
the old to the new."
But this means that every simple DML (insert, update, delete) and select fully supports the ora_rowscn in plsql and data integrity.
Inserting a row and reading the same data is not an option, cause I can retrieve the rowid in the returning clause of an insert statement too. (And thats the way I expect the ora_rowscn to work too.)
September 09, 2006 - 11:42 am UTC
when you UPDATE or DELETE, you could re-read the ora_rowscn to compare it to the value you read when you first read the row out.
for INSERT - you never read the row out the first time, hence, there is no ora_rowscn to re-read and compare to!
You do not need it for "insert", you just created the row (nothing to re-read) and you have the row locked (no one can modify it till you commit)
Matthias, September 11, 2006 - 4:21 am UTC
Hello,
thank you for your answer.
Lets go into the deep of our application.
In our application we decided to abstract the handling of data from their storage in tables. That means we have some kind of "business objects".
If an user inserts a new object, these object inserts its data into the desired tables - don't knowing when the data will be commited and seen by other users.
This object can also be given to the next method/form which altered the object in some way so that an update will be necessary.
How can this object be sure, that it can make a legal update without having a valid ora_rowscn?
Well, we can discuss if and when it will be necessary that an insert statement should return a new ora_rowscn number or not. As long, as people wanted it (see Bug 5118104), it should be implemented. Before ora_rowscn people added a column to their tables to implement optmistic locking. Thats what they don't need to do anymore if they could use ora_rowscn in the same way the used the extra column.
Why does the behavior from ora_rowscn differs from the old way...?
September 11, 2006 - 9:56 am UTC
ah, since you have gone for the seriously "non-performant route", I have no problem just telling you to read it out after the fact. It doesn't really matter since this "abstraction" layer is adding so much overhead anyway.
for enhancement requests, you have to use support. It isn't going to happen because you convince ME, I'm not really relevant in that process.
rowdependencies - online rebuild
Piyush, August 12, 2007 - 3:35 pm UTC
Hi Tom!
As suggested I am trying to rebuild rowdepencies on an existing table.
Please confirm if the following process will work on Oracle 10G (Rel1 and Rel2)...
GRANT execute ON dbms_redefinition TO piyush;
--- logged in with piyush
create table online_original
(
col1 number primary key,
text1 varchar2(10) not null,
text2 varchar2(10)
);
insert into online_original
select rownum, 'sample' || rownum, 'next' || rownum
from user_objects
where rownum <=10;
commit;
-- create table to be used to enable rowdependencies attribute of the table
create table online_staging
(
col1 number primary key,
text1 varchar2(10) not null,
text2 varchar2(10)
)
rowdependencies;
EXEC dbms_redefinition.can_redef_table ('piyush', 'online_original');
-- process 1 (this is one way)
-- if there is no exception, then proceed
EXECUTE dbms_redefinition.start_redef_table ('piyush', 'online_original', 'online_staging');
EXECUTE dbms_redefinition.SYNC_INTERIM_TABLE ('piyush', 'online_original', 'online_staging');
EXECUTE dbms_redefinition.finish_redef_table ('piyush', 'online_original', 'online_staging');
-- process 2
EXECUTE dbms_redefinition.COPY_TABLE_DEPENDENTS ('piyush', 'online_staging', 'online_original');
Please confirm if I am correct.
Moreover, please let me know if I have missed out on any step which may be essential. (alternative process if any)
Thanks n Regards,
Piyush
August 15, 2007 - 10:48 am UTC
well, you have extra steps - but let me ask you this
when you tested it, did it do what you needed.
you have the steps out of order - start redef, copy dependents then finish redef.
Notification of followup via email
Mathew Butler, August 15, 2007 - 1:05 pm UTC
Hi Tom,
I submitted the original question and just received an email advising me that you had added a followup.
I wondered if there was any plans to update the site to allow for changes of email? I've posted questions here under several email addresses and my email has changed ( email changes sometimes, even though my employer hasn't changed in 10 years )
Best Regards,
Clarification of views for UPDATE/DELETE/INSERT coupled with VPD
M Jensen, June 13, 2008 - 6:15 am UTC
Hi,
We would ideally like to use ora_rowscn with rowdependencies enabled in order to implement optimistic locking. However, we also wish to use VPD on some of our tables.
I've managed to expose the ora_rowscn through a view on the base table and to apply the VPD policy to the view. Without the VPD policy on the table I can insert/update/delete through the view - but with the VPD policy I get an ORA-4091 mutating table error.
I may well be wrong but I therefore suspect the VPD implementation uses triggers internally that may cause the mutation (although none are to be found for the table/view in the data dictionary)?
I've therefore toyed with using INSTEAD OF triggers on the view for updates to the table but haven't so far been able to get this to work using ora_rowscn to perform optimistic locking, i.e. that no rows are updated when the SCN has changed.
Would you have any ideas as to how I can workaround this?
Alternatively, I guess a timestamp or revision column would be the way forward in our case.
Thanks in advance for your help and comments.
June 13, 2008 - 8:27 am UTC
I need a test case to work with...
ops$tkyte%ORA10GR2> create table dept rowdependencies as select * from scott.dept;
Table created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create or replace function my_function( p_schema in varchar2, p_object in varchar2 ) return varchar2
2 as
3 begin
4 return 'deptno = 10';
5 end;
6 /
Function created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create or replace view deptv as select dept.*, ora_rowscn scn from dept;
View created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> begin
2 dbms_rls.add_policy
3 ( object_schema => user,
4 object_name => 'DEPTV',
5 policy_name => 'MY_POLICY',
6 function_schema => user,
7 policy_function => 'my_function',
8 statement_types => 'select, insert, update, delete' ,
9 update_check => TRUE );
10 end;
11 /
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 Accounting NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
ops$tkyte%ORA10GR2> select * from deptv;
DEPTNO DNAME LOC SCN
---------- -------------- ------------- ----------
10 Accounting NEW YORK 64971234
ops$tkyte%ORA10GR2> insert into deptv (deptno,dname,loc) values ( 10,'xxx','yyy');
1 row created.
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2> select * from deptv;
DEPTNO DNAME LOC SCN
---------- -------------- ------------- ----------
10 Accounting NEW YORK 64971234
10 xxx yyy 64971260
ops$tkyte%ORA10GR2> update deptv set dname = 'abc' where dname = 'xxx';
1 row updated.
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2> select * from deptv;
DEPTNO DNAME LOC SCN
---------- -------------- ------------- ----------
10 Accounting NEW YORK 64971234
10 abc yyy 64971263
ops$tkyte%ORA10GR2> delete from deptv where dname = 'abc';
1 row deleted.
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2> select * from deptv;
DEPTNO DNAME LOC SCN
---------- -------------- ------------- ----------
10 Accounting NEW YORK 64971234
Thanks - update_check => TRUE did the trick
M Jensen, June 13, 2008 - 8:58 am UTC
Hi Tom,
Thanks for your response - I was missing update_check => TRUE in order to prevent ORA-4091. I no longer have a need for instead-of triggers.
Thanks for your help, very much appreciated!
Need to specify locking and transaction boundaries in examples
Andrew Wolfe, August 29, 2008 - 12:36 pm UTC
Tom,
When I read this in conjunction with the disclaimers in the Oracle docs, I am concluding that a SELECT FOR UPDATE NOWAIT is needed to prevent race conditions between separate sessions accessing the same row.
Also, I think you need to more fully describe the COMMITs interior to your plsql loops in order to make clear what are the transaction boundaries.
Your answer makes sense in the three-tier world with brief database interactions, and pooled connections that are cleaned between uses.
For those still in a client/server mindset with 'static' DB sessions holding transactions open for long periods, I feel you need to clarify how to use ORA_ROWSCN for optimistic locking.
Best,
Andrew Wolfe
Optimistic Locking Approach Doesn't Work
Jumping Jimmy Jeeves, September 12, 2008 - 9:31 am UTC
The approach described for optimistic locking doesn't work:
update <some_table>
set <some_columns> = <some_values>
where <predicated key column> = <some key value>
and ora_rowscn = p_old_scn;
If (SQL%rowcount = 0) Then
<raise an exception>
End If;
In the case where two (or more) sessions concurrently update the same record. Subsequent updates enqueues behind the first.
When the first session commits, the second session proceeds with the update even though the ora_rowscn has changed because it consistently sees the unchanged value of ora_rowscn.
This isn't a flaw of ora_rowscn, just a failure of the approach.
September 16, 2008 - 1:37 pm UTC
arg, in progress bug 7338384
suggested workaround
select for update by ora_rowscn
then update by ora_rowscn
thanks for that followup, appreciate it.
Henry, September 12, 2008 - 2:57 pm UTC
It appears that the bug referenced by Jonathan Lewis arises because ora_rowscn is not dealt with properly in the purview of write consistency.
According to the 11g Oracle Advanced Application Developer¿s Guide, ora_rowscn the ¿Uses of ORA_ROWSCN in application development include concurrency control and client cache invalidation.¿ However, it cannot be used in an optimistic locking scenario since ora_rowscn is not handled properly within the scope of Write Consistency (http://tkyte.blogspot.com/2005/08/something-different-part-i-of-iii.html). Write Consistency makes sure that updates are applied to a consistent set of data.
An update statement is effectively comprised of a SELECT which gathers the rows to be updated, followed by the update itself. Oracle¿s Write Consistency checks that the values which are used to collect the result set to be updated have not changed. We can easily see different behavior, depending on the SQL filters (WHERE clause) as demonstrated in the following cases. We also filter on ora_rowscn to see how it (mis)behaves.
Our tests used a table, FOO, containing three rows of data.
DROP TABLE foo purge;
CREATE TABLE foo (x number, y number) ROWDEPENDENCIES;
INSERT INTO foo VALUES (1,1);
commit;
INSERT INTO foo VALUES (2,2);
commit;
INSERT INTO foo VALUES (3,3);
commit;
Our two cases consist of:
1. Session #1: update x for all rows in FOO.
2. Session #2: update x for a single row in FOO. This row is filtered either by x (which will change after session #1 commits) or by y. This update waits until session #1 commits.
3. Session #1: commit
4. final result set depends on whether step 2 filtered on x or y.
CASE #1
In Case #1, session #2 selects the rows to update based on the value of y, which does not change. So the record selected at the outset is updated using the post-commit (current) value of x.
sess1 21:16:02> update foo set x=x+1 where y>0;
3 rows updated.
sess2 21:17:55> update foo set x=2*x where y=2;
sess1 21:18:22> commit;
Commit complete.
[sess2] 1 row updated.
sess2 21:19:18> select * from foo;
X Y
---------- ----------
2 1
6 2
4 3
CASE #2
In Case #2, session #2 selects the rows based on the value of x, which changes. So it needs to reselect the result set after session #1 commits. It does this prior to its update. The update is thus applied to a different row.
sess1 21:12:54> update foo set x=x+1 where y>0;
3 rows updated.
sess2 21:12:44> update foo set x=2*x where x=2;
sess1 21:13:19> commit;
Commit complete.
[sess2] 1 row updated.
sess2 21:15:02> select * from foo;
X Y
---------- ----------
4 1
3 2
4 3
ORA_ROWSCN
What if we filter session #2 on ora_rowscn? Since the commit from session #1 changes the value of ora_rowscn, one would expect this case would be analogous to Case #2. IT IS NOT!! It behaves, incorrectly It follows case #1.
sess1 21:24:37> update foo set x=x+1 where y>0;
3 rows updated.
sess2 21:20:35> update foo set x=2*x where ora_rowscn=11138156;
sess1 21:25:14> commit;
Commit complete.
[sess2] 1 row updated.
sess2 21:26:39> select * from foo;
X Y
---------- ----------
2 1
6 2
4 3
We can further confirm that this is a Write Consistency issue by examining the state of the blocks in buffer cache (using x$bh). To do this, we flush the buffer cache following session #2¿s update statement (step #2) and query x$bh (v$bh would have been sufficient for this, but I was also looking at some extra data) after session #1¿s commit (step #3).
An UPDATE requires both consistent reads (cr) and current reads (xcur) of data blocks. The cr gets a consistent result set of rows to be updated. It effectively SELECTs the rows using the WHERE clause in the UPDATE statement. After collecting these rows, a current read is done prior to update in order to make sure we still have a consistent set. If the filtered field has changed in any of these records we no longer have a consistent set of records and need to redo the SELECT using another cr.
CASE #1
Flushing and querying the buffer cache immediately after session #1 commits, we find a single xcur buffer.
monitor 21:19:11> /
ADDR FILE# BLOCK# STATUS
---------------- ---------- ---------- ----------
0000002A96DAEFF8 4 997 free
0000002A96DAF140 4 997 free
0000002A96DAF288 4 997 free
0000002A96DAF3D0 4 997 free
0000002A96DAF518 4 997 free
0000002A96DAF660 4 997 free
0000002A96DAF7A8 4 997 xcur
7 rows selected.
CASE #2
monitor 21:14:52> @xbh
ADDR FILE# BLOCK# STATUS
---------------- ---------- ---------- ----------
0000002A96DAF660 4 997 cr
0000002A96DAF7A8 4 997 xcur
As expected, we now have an extra cr, as we need to redo the select part of our statement.
ORA_ROWSCN
monitor 21:26:32> @xbh
ADDR FILE# BLOCK# STATUS
---------------- ---------- ---------- ----------
0000002A96A0E9A0 4 997 free
0000002A96A0EAE8 4 997 free
0000002A96A0EC30 4 997 free
0000002A96A0ED78 4 997 free
0000002A96DAEFF8 4 997 free
0000002A96DAF140 4 997 free
0000002A96DAF288 4 997 free
0000002A96DAF3D0 4 997 free
0000002A96DAF518 4 997 free
0000002A96DAF660 4 997 free
0000002A96DAF7A8 4 997 xcur
11 rows selected.
We see that the additional consistent read never took place, even though it should have.
Apparently, ora_rowscn is not being treated as real data even though it is stored with the rest of the row¿s data in the data block when the table is created using ROWDEPENDENCIES. Just because ora_rowscn is called a pseudo-column doesn¿t mean that its data is not physically stored.
enabling rowdependencies in existing table
Piyush, September 21, 2011 - 6:10 am UTC
Hi Tom, After 3 years when I again faced the issue. I tried again to use dbms_redefinition package to enable rowdepencies in Oracle 10G Rel 2 table. Unfortunately, when i extracted back the definition of the original table, it did not show up rowdependencies element. Could you please confirm.
September 21, 2011 - 9:41 am UTC
ops$tkyte%ORA10GR2> create table t ( x int );
Table created.
ops$tkyte%ORA10GR2> select dbms_metadata.get_ddl( 'TABLE', 'T' ) from dual;
DBMS_METADATA.GET_DDL('TABLE','T')
-------------------------------------------------------------------------------
CREATE TABLE "OPS$TKYTE"."T"
( "X" NUMBER(*,0)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS"
ops$tkyte%ORA10GR2> alter table t enable row movement;
Table altered.
ops$tkyte%ORA10GR2> select dbms_metadata.get_ddl( 'TABLE', 'T' ) from dual;
DBMS_METADATA.GET_DDL('TABLE','T')
-------------------------------------------------------------------------------
CREATE TABLE "OPS$TKYTE"."T"
( "X" NUMBER(*,0)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS" ENABLE ROW MOVEMENT
no problem for me in 10.2.0.5
Rowdepencies
Piyush Agarwal, October 13, 2011 - 2:34 am UTC
Hi Tom, I asked about enabling row dependencies [ora_rowscn feature] but you replied about enabling row movement which is quite simple.
Thanks n Regards,
Piyush Agarwal
October 13, 2011 - 7:39 am UTC
you are correct sorry about that.
ops$tkyte%ORA10GR2> create table t1
2 as
3 select * from all_objects;
Table created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> alter table t1 add constraint t1_pk primary key(object_id);
Table altered.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create table t2 (
2 OWNER VARCHAR2(30),
3 OBJECT_NAME VARCHAR2(30),
4 SUBOBJECT_NAME VARCHAR2(30),
5 OBJECT_ID NUMBER,
6 DATA_OBJECT_ID NUMBER,
7 OBJECT_TYPE VARCHAR2(19),
8 CREATED DATE,
9 LAST_DDL_TIME DATE,
10 TIMESTAMP VARCHAR2(19),
11 STATUS VARCHAR2(7),
12 TEMPORARY VARCHAR2(1),
13 GENERATED VARCHAR2(1),
14 SECONDARY VARCHAR2(1),
15 NAMESPACE NUMBER,
16 EDITION_NAME VARCHAR2(30)
17 ) rowdependencies;
Table created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> exec dbms_redefinition.can_redef_table( user, 'T1' );
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> exec dbms_redefinition.start_redef_table( user, 'T1', 'T2', orderby_cols => 'OBJECT_ID' )
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> variable nerrors number
ops$tkyte%ORA10GR2> begin
2 dbms_redefinition.copy_table_dependents
3 ( user, 'T1', 'T2',
4 copy_indexes => dbms_redefinition.cons_orig_params,
5 num_errors => :nerrors );
6 end;
7 /
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> print nerrors
NERRORS
----------
0
ops$tkyte%ORA10GR2> exec dbms_redefinition.finish_redef_table( user, 'T1', 'T2' );
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> drop table t2;
Table dropped.
ops$tkyte%ORA10GR2> select dbms_metadata.get_ddl( 'TABLE', 'T1' ) from dual;
DBMS_METADATA.GET_DDL('TABLE','T1')
-------------------------------------------------------------------------------
CREATE TABLE "OPS$TKYTE"."T1"
( "OWNER" VARCHAR2(30) CONSTRAINT "SYS_C0012216" NOT NULL ENABLE NOVALIDATE,
"OBJECT_NAME" VARCHAR2(30) CONSTRAINT "SYS_C0012217" NOT NULL ENABLE NOVALIDAT
E,
"SUBOBJECT_NAME" VARCHAR2(30),
"OBJECT_ID" NUMBER CONSTRAINT "SYS_C0012218" NOT NULL ENABLE NOVALIDATE,
"DATA_OBJECT_ID" NUMBER,
"OBJECT_TYPE" VARCHAR2(19),
"CREATED" DATE CONSTRAINT "SYS_C0012219" NOT NULL ENABLE NOVALIDATE,
"LAST_DDL_TIME" DATE CONSTRAINT "SYS_C0012220" NOT NULL ENABLE NOVALIDATE,
"TIMESTAMP" VARCHAR2(19),
"STATUS" VARCHAR2(7),
"TEMPORARY" VARCHAR2(1),
"GENERATED" VARCHAR2(1),
"SECONDARY" VARCHAR2(1),
"NAMESPACE" NUMBER,
"EDITION_NAME" VARCHAR2(30),
CONSTRAINT "T1_PK" PRIMARY KEY ("OBJECT_ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS" ENABLE NOVALIDATE
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS" <b>ROWDEPENDENCIES
</b>
ops$tkyte%ORA10GR2> drop table t1;
Table dropped.
you'll have to help me reproduce your issue. I get rowdependencies just fine.
timestamp or number version column
Branka, May 17, 2012 - 9:48 am UTC
If I use timestamp or number version column, and 2 transactions try to update same record at the same time (millisecond precision)
Update aa
Where pk_aa = :pk_aa1
And version_id=:old_version_id
Will second transaction overwrite first one? How can I test it? How would it be different than using ORA_ROWSCN?
May 18, 2012 - 2:23 am UTC
in order for the millisecond problem to exist the following would have to be true:
a) the record was successfully updated and committed by some transaction at time X (the update and commit happen in the same millisecond)
b) the record was read out by two NEW transactions at exactly time X (still the same millisecond)
c) the record was updated by the two new transactions (and at least one of them committed!) at exactly time X (the same millisecond still)
All of the above has to happen to that record in a single millisecond.