Does canceling update operation perform automatic rollback
-
16-02-2021 - |
Question
I ran into a bit of confusion. I'm under the belief that database operations are automatic - that is either the query succeeds or the transaction is automatically rolledback. For example - if you have a long running UPDATE statement and you "cancel" it before it finishes - IE clicking red circle X button in SQL Developer (which you should receive a ORA-01013: user requested cancel of current operation error). Upon canceling the query the query is rolled back and no rows were affected. I believe the same should hold true for DELETE statements.
I looked around for some documentation on it and I found this article that really isn't authoritative.
La solution
If you do that, the statement is rolled back, not the transaction. Below I hit Ctrl+C after starting the UPDATE.
SQL> drop table t1 purge;
Table dropped.
SQL> create table t1 as select * from dba_objects;
Table created.
SQL> insert into t1 select * from t1;
23849 rows created.
SQL> insert into t1 select * from t1;
47698 rows created.
SQL> insert into t1 select * from t1;
95396 rows created.
SQL> insert into t1 select * from t1;
190792 rows created.
SQL> insert into t1 select * from t1;
381584 rows created.
SQL> commit;
Commit complete.
SQL> conn bp/bp
Connected.
SQL> select name, value from v$mystat mt join v$statname sn on (mt.statistic# = sn.statistic#) where sn.name in ('transaction rollbacks', 'rollback changes - undo records applied');
NAME VALUE
---------------------------------------------------------------- ----------
rollback changes - undo records applied 0
transaction rollbacks 0
SQL> set timing on
SQL> update t1 set object_id = object_id + 1;
update t1 set object_id = object_id + 1
*
ERROR at line 1:
ORA-01013: user requested cancel of current operation
Elapsed: 00:00:01.51
SQL> select name, value from v$mystat mt join v$statname sn on (mt.statistic# = sn.statistic#) where sn.name in ('transaction rollbacks', 'rollback changes - undo records applied');
NAME VALUE
---------------------------------------------------------------- ----------
rollback changes - undo records applied 173323
transaction rollbacks 1
Elapsed: 00:00:00.00
SQL>
1 transaction was rolled back and 173323 undo records were applied to perform the rollback. But that is because I had no other change in that transaction.
If I have other changes in the transaction, those changes will not be rolled back automatically:
SQL> conn bp/bp
Connected.
SQL> select name, value from v$mystat mt join v$statname sn on (mt.statistic# = sn.statistic#) where sn.name in ('transaction rollbacks', 'rollback changes - undo records applied');
NAME VALUE
---------------------------------------------------------------- ----------
rollback changes - undo records applied 0
transaction rollbacks 0
Elapsed: 00:00:00.00
SQL> insert into t1(object_id) values (-1);
1 row created.
Elapsed: 00:00:00.00
SQL> select count(*) from t1 where object_id = -1;
COUNT(*)
----------
1
Elapsed: 00:00:00.09
SQL> select name, value from v$mystat mt join v$statname sn on (mt.statistic# = sn.statistic#) where sn.name in ('transaction rollbacks', 'rollback changes - undo records applied');
NAME VALUE
---------------------------------------------------------------- ----------
rollback changes - undo records applied 0
transaction rollbacks 0
Elapsed: 00:00:00.00
SQL> update t1 set object_id = object_id + 1;
update t1 set object_id = object_id + 1
*
ERROR at line 1:
ORA-01013: user requested cancel of current operation
Elapsed: 00:00:02.16
SQL> select name, value from v$mystat mt join v$statname sn on (mt.statistic# = sn.statistic#) where sn.name in ('transaction rollbacks', 'rollback changes - undo records applied');
NAME VALUE
---------------------------------------------------------------- ----------
rollback changes - undo records applied 274294
transaction rollbacks 0
Elapsed: 00:00:00.01
SQL> select count(*) from t1 where object_id = -1;
COUNT(*)
----------
1
Elapsed: 00:00:00.04
SQL> rollback;
Rollback complete.
Elapsed: 00:00:00.00
SQL> select count(*) from t1 where object_id = -1;
COUNT(*)
----------
0
Elapsed: 00:00:00.06
SQL> select name, value from v$mystat mt join v$statname sn on (mt.statistic# = sn.statistic#) where sn.name in ('transaction rollbacks', 'rollback changes - undo records applied');
NAME VALUE
---------------------------------------------------------------- ----------
rollback changes - undo records applied 274295
transaction rollbacks 1
Elapsed: 00:00:00.00
Notice how the value of transaction rollbacks remained 0 this time, and how the INSERT was not rolled back, and I was still able to rollback the transaction manually.