Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Yogesh.

Asked: April 25, 2007 - 12:22 am UTC

Last updated: April 27, 2007 - 10:43 am UTC

Version: 8.1.7

Viewed 1000+ times

You Asked

This is a theoritical question.
The question is, what happens to the transaction (row) locks after the command "Rollback to SavePoint" is given.
I will tell you a situation; and try to reply the question myself as per my thinking. Please tell me wherever I am wrong.

09:21:06 stores1@ >create table t (r int, c int);

Table created.

(note - some editing was done to remove syntax errors in the INSERT statements)

real: 31
09:21:19 stores1@ >insert into t values (1,1);

1 row created.

real: 16
09:21:49 stores1@ >insert into t values (2,2);

1 row created.

real: 16
09:21:56 stores1@ >commit
09:21:58 2 ;

Commit complete.

real: 16
09:21:59 stores1@ >update t set c = c + 1 where c = 1;

1 row updated.

real: 15
09:22:13 stores1@ >savepoint sp1;

Savepoint created.

real: 16
09:22:25 stores1@ >update t set c = c + 1 where c = 2;

2 rows updated.

real: 15
09:22:39 stores1@ >rollback to savepoint sp1;

Rollback complete.

real: 16
09:22:48 stores1@ >spo off

Broadly, following occurs in the last transaction (after commit, of course);

(1) First update starts the transaction
(1.1) One row (r=1) is selected and locked for update
(1.2) The locked row (r=1) is updated

(2) Transaction continues with savepoint SP1 marked

(3.1) Second update takes one row (r=1) and finds that it is already locked
(3.2) One row (r=1) is updated
(3.3) one (another) row (r=2) is locked for update
(3.4) the row (r=2) is updated

(4) Rollback to Savepoint SP1
(4.1) Rollbacks the update of the row (r=1) against (3.2) above
(4.2) Rollbacks the update of the row (r=2) against (3.4) above

But, what happens to the row locks ?

Oracle does not keep track of row level lockings.
It is not able to sense the difference between lock on row one (r=1) and row two (r=2).
The transaction entry in the block header is quite small while the number of savepoints supported is unlimited.
Therefore, oracle cannot (and hence, will not) release lock on the row (r=2).
Lock on row (r=1) is not be released, since it is before savepoint.

Please throw more light !

and Tom said...

In your example - the row lock on the second row modified will be released and any subsequent transactions will be able to get a lock on it, this is demonstrated by the fact the first autonomous transaction succeeds and the second was blocked:



ops$tkyte%ORA10GR2> create table t ( x int, y int );

Table created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> insert into t values ( 1, 0 );

1 row created.

ops$tkyte%ORA10GR2> insert into t values ( 2, 0 );

1 row created.

ops$tkyte%ORA10GR2> commit;

Commit complete.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> update t set y = 1 where x = 1;

1 row updated.

ops$tkyte%ORA10GR2> savepoint foo;

Savepoint created.

ops$tkyte%ORA10GR2> update t set y = 2 where x = 2;

1 row updated.

ops$tkyte%ORA10GR2> rollback to foo;

Rollback complete.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> declare
  2          pragma autonomous_transaction;
  3  begin
  4          update t set y = 2 where x = 2;
  5          commit;
  6  end;
  7  /

PL/SQL procedure successfully completed.

ops$tkyte%ORA10GR2> declare
  2          pragma autonomous_transaction;
  3  begin
  4          update t set y = 1 where x = 1;
  5          commit;
  6  end;
  7  /
declare
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
ORA-06512: at line 4




Now, it we did something like:

update where x=1;
savepoint foo;
update where x=2;


and then in another session:
update where x=2 <<=== this blocks

and then in the first session:

rollback to foo;

you would NOT see the second session 'unblock', that is because the second session is blocked on the first session - NOT on the row the first session locked, but on the first session itself.

some third session would be able to lock where x=2 right now, but that second session would stay blocked...

Rating

  (4 ratings)

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

Comments

Blocks on the session or transaction ?

Jay, April 25, 2007 - 11:38 am UTC

In Tom's reply above, doesn't the second session block on the transaction of the first session rather than on the first session itself ?
Tom Kyte
April 25, 2007 - 1:21 pm UTC

blocks on the transaction - yes. sorry, it should say the sessions transaction

point was, it is not blocked on the row, when the row becomes unlocked - that second session is still blocked

until the first session commits or rollsback the entire transaction

Lock & Rollback to SavePoint

Yogesh Purabiya, April 26, 2007 - 12:45 am UTC

Thanks, Tom ; this is short and sweet !

But, still, I would like to know how the Oracle differentiates the rows with respect to their locks & Save points (i.e., which rows were locked before the savepoint and which were locked after the savepoint).
Tom Kyte
April 26, 2007 - 11:48 am UTC

undo is like a linked list, just walk it backwards to find the marker..... rolling back as you go.

Locks and Undo

Yogesh Purabiya, April 26, 2007 - 11:32 pm UTC

Thanks again, Tom !
I understand that savepoints & locks & DML operations, all are there in the UNDO.

This raises two more queries (A) & (B) below:

(A) Whenever we see UNLIMITED (like, locks, savepoints, transactions, sessions, etc), is it better to think of Block Header, UNDO & REDO ?
And, whenever we see LIMITED (like cursors, processes, etc), is it better to think of some other structure ?

(B) This query is less related to the original question.

When does Oracle make an entry of a lock in the UNDO ?
(1) Just Before / Soon After the row is locked
OR
(2) Just Before / Soon After the row is actually changed / deleted ?

Consider this :


08:44:11 stores1@ >create table pt (pk int primary key);

Table created.

real: 78
08:44:23 stores1@ >create table ct (fk int references pt);

Table created.

real: 32
08:44:36 stores1@ >insert into pt values (1);

1 row created.

real: 16
08:44:44 stores1@ >commit;

Commit complete.

real: 16
08:44:50 stores1@ >insert into ct
08:44:56 2 select 1 from all_objects;

4847 rows created.

real: 1172
08:45:06 stores1@ >r
1 insert into ct
2* select 1 from all_objects

4847 rows created.

real: 1609
08:45:11 stores1@ >r
1 insert into ct
2* select 1 from all_objects

4847 rows created.

real: 766
08:45:13 stores1@ >r
1 insert into ct
2* select 1 from all_objects

4847 rows created.

real: 531
08:45:18 stores1@ >r
1 insert into ct
2* select 1 from all_objects

4847 rows created.

real: 485
08:45:20 stores1@ >commit;

Commit complete.

real: 32
08:45:24 stores1@ >select count(*) from ct;

COUNT(*)
----------
24235
----------
24235

real: 31
08:45:30 stores1@ >-- no index on the child table ct
08:45:41 stores1@ >
08:45:42 stores1@ >update pt set pk = 1;

1 row updated.

real: 16
08:45:50 stores1@ >commit;

Commit complete.

real: 16
08:45:52 stores1@ >
08:45:55 stores1@ >
08:45:55 stores1@ >
08:45:55 stores1@ >-- one more case
08:46:02 stores1@ >
08:46:04 stores1@ >update pt set pk = 1;

1 row updated.

real: 16
08:46:11 stores1@ >rollback;

Rollback complete.

real: 15
08:46:14 stores1@ >spo off

What is the effect of this on the size of UNDO / REDO ?
Tom Kyte
April 27, 2007 - 10:43 am UTC

a) i don't understand your distinctions.


b) locks are attributes on blocks, block modifications are recorded in undo. To "lock" a row, you modify a block, before/as you modify a block, undo is generated.

Locks & Undo

Yogesh Purabiya, May 04, 2007 - 4:01 am UTC

Thank you, Tom !

I believe that it is true for Transaction Entries as well. If a transaction entry for the current transaction is made in the block after the savepoint SP1, then "Rollback to savepoint SP1;" will release the transaction entry as well, as it is was put in the UNDO.

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