Você está na página 1de 4

Autonomous Transaction can cause locking

PURPOSE
-------
The purpose of this bulletin is to explain how autonomous transactions can cause
locking problems and how to avoid this problem.
SCOPE & APPLICATION
-------------------
The note is written for intermediate to advanced level developers, users and DBAs.
It does not apply to any pre 8i versions of Oracle or PL/SQL.
LOCKING CAUSED BY AUTONOMOUS TRANSACTIONS
-------------------------------------------
Autonomous transactions were introduced in 8i. Oracle 8i provides the ability to temporarily
suspend the current transaction and begin another. This second transaction is known as an
Autonomous transaction and, as the name suggests, runs independently of its parent. The
Autonomous or child transaction can commit or rollback as applicable with the execution of
the parent transaction being resumed upon its completion. The parent may then perform
further operations and commit or rollback without affecting the outcome of any operations
performed within the child.
The introduction of Autonomous transactions allows users to more easily develop modular,
reusable components. Calling applications no longer need to be aware of what components
do internally and the components themselves need no knowledge of which operations an
application has performed prior to calling. More information on Autonomous transactions
can be found in
Note:65961.1 Oracle8i: Autonomous Transactions
Because the parent and child transactions are independent, they also are not able to share
any locks; if a parent transaction has a resource locked that a child attempts to obtain, then
a deadlock situation occurs. In this case, the offending statement is automatically rolled
back with an "ORA-00060: deadlock detected while waiting for resource" exception raised
within the child. Information on how to troubleshoot a deadlock can be found in:
Note: 164661.1 Ora-60 And Deadlocks Most Common Causes
When a deadlock is encountered, an ORA-60 error message is thrown and a trace file is
written to the user_dump_dest. The objects involved in the deadlock will be named in the
trace file. You can use the ALL_SOURCE, DBA_SOURCE, or USER_SOURCE views to
determine if the object was created as an autonomous transaction.
A trace file generated with the 10046 event will also tell you if you are dealing with an
autonomous transaction.
The best way to avoid deadlocks is to design your code to such that two independent
transactions do not need to accessing the same lock at the same time. To resolve a
deadlock associated with an autonomous transaction you can either issue a commit or a
rollback command before and after the autonomous transaction.
Examples
To recreate the following examples you will need to create the table dept as follows:
CREATE TABLE DEPT
(DEPTNO NUMBER(2) CONSTRAINT PK_DEPT PRIMARY KEY,
DNAME VARCHAR2(14) ,
LOC VARCHAR2(13) ) ;
Populate the dept table with the following values:
INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK');
INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
INSERT INTO DEPT VALUES (30,'SALES','CHICAGO');
INSERT INTO DEPT VALUES (40,'OPERATIONS','BOSTON');
The following example shows an Autonomous transactions that causes a deadlock situation:
Create or Replace Package AUTON_LOCK
as
procedure AUTON_LOCK_LOCAL (Dname IN OUT VARCHAR2, deptno IN OUT number, Loc
IN OUT VARCHAR2);
procedure AUTON_LOCK_MAIN(Dname IN OUT VARCHAR2, deptno IN OUT number, Loc IN
OUT VARCHAR2);
END AUTON_LOCK;
/
show errors
/
CREATE OR REPLACE PACKAGE BODY AUTON_LOCK
AS
PROCEDURE AUTON_LOCK_LOCAL (Dname IN OUT VARCHAR2, deptno IN OUT number, Loc
IN OUT VARCHAR2) as
pragma AUTONOMOUS_TRANSACTION;
begin
Update dept set dname='CONSULTING' where deptno=20;
Update dept set Loc='ORLANDO' where deptno=10;
end;
procedure AUTON_LOCK_MAIN(Dname IN OUT VARCHAR2, deptno IN OUT number, Loc IN
OUT VARCHAR2) as
begin
Update dept set Dname='SUPPORT' where deptno=10;
AUTON_LOCK_LOCAL(Dname, deptno, Loc);
update dept set loc='QQQ' where deptno=20;
end;
end AUTON_LOCK;
/
show errors
Now try to run this package using the following:
declare
Dname varchar2(14) :='ACCOUNTING';
deptno number :=10;
Loc varchar2(13) :='New York';
begin AUTON_LOCK.AUTON_LOCK_MAIN(Dname, deptno, Loc);
end; /
Note that this causes the database to lock and returns the following:
SQL> declare
2 Dname varchar2(14) :='ACCOUNTING';
3 deptno number :=10;
4 Loc varchar2(13) :='New York';
5 begin AUTON_LOCK.AUTON_LOCK_MAIN(Dname, deptno, Loc);
6 end;
7 /
declare
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
ORA-06512: at "SCOTT.AUTON_LOCK", line 10
ORA-06512: at "SCOTT.AUTON_LOCK", line 21
ORA-06512: at line 5
The deadlock occurs because the MAIN and LOCAL procedures are trying to modify the same
records. Since the LOCAL procedure is autonomous, it cannot see that the MAIN procedure
has acquired a lock on the row it is trying to access. The MAIN procedure also cannot see
that the LOCAL procedure has acquired a lock on the row it needs. This is considered a
deadlock because the MAIN procedure cannot proceed as it is waiting on a lock the LOCAL
procedure is holding and the LOCAL procedure cannot proceed because it is waiting on a
lock the MAIN procedure is holding. This deadlock throws an ORA-00060 error message and
generates a trace
file that is dumped into the user dump destination. The trace file will look something like
this:
Dump file C:\oracle\admin\orcl9i\udump\ORA01720.TRC Sun Jan 12 16:36:17 2003
ORACLE V9.0.1.1.1 - Production vsnsta=0 vsnsql=10 vsnxtr=3
Windows 2000 Version 5.0 , CPU type 586
Oracle9i Enterprise Edition Release 9.0.1.1.1 - Production With the Partitioning option
JServer Release 9.0.1.1.1 - Production Windows 2000 Version 5.0 , CPU type 586
Instance name: orcl9i
Redo thread mounted by this instance: 1
Oracle process number: 12
Windows thread id: 1720, image: ORACLE.EXE
*** 2003-01-12 16:36:17.000
*** SESSION ID:(7.36) 2003-01-12 16:36:17.000
DEADLOCK DETECTED
Current SQL statement for this session:
UPDATE dept set Loc='ORLANDO' where deptno=10
----- PL/SQL Call Stack -----
object line object
handle number name
79F5A0A0 10 package body SCOTT.AUTON_LOCK
79F5A0A0 21 package body SCOTT.AUTON_LOCK
79ED6BBC 5 anonymous block
The following deadlock is not an ORACLE error. It is a deadlock due to user error in the
design of an application or from issuing incorrect ad-hoc SQL. The following information may
aid in determining the deadlock:
Deadlock graph:
---------Blocker(s)-------- ---------Waiter(s)---------
Resource Name process session holds waits process session holds waits
TX-00010010-000002dd 12 7 X 12 7 X
session 7: DID 0001-000C-00000002 session 7: DID 0001-000C-00000002
Rows waited on:
Session 7: obj - rowid = 00007D76 - AAAH12AABAAAO+BAAA
(dictionary objn - 32118, file - 1, block - 61313, slot - 0)
SQL statements executed by the waiting sessions:
===================================================
PROCESS STATE
This shows us that the object causing the deadlock is SCOTT.AUTON_LOCK.
We can query the view USER_OBJECTS to determine what type of object AUTON_LOCK
is as follows:

SQL> SELECT OBJECT_TYPE


2 FROM USER_OBJECTS
3 WHERE OBJECT_NAME='AUTON_LOCK';
OBJECT_TYPE
------------------
PACKAGE
PACKAGE BODY
We can then query the source code used to create the object using the following:
SQL> set pagesize 50;
SQL> SELECT TEXT FROM USER_SOURCE
2 WHERE NAME='AUTON_LOCK'
3 AND TYPE='PACKAGE BODY';
TEXT
----------------------------------------------------------------------------------------------------
PACKAGE BODY AUTON_LOCK
AS
PROCEDURE AUTON_LOCK_LOCAL (Dname IN OUT VARCHAR2, deptno IN OUT number, Loc
IN OUT VARCHAR2) as
pragma AUTONOMOUS_TRANSACTION;
begin
Update dept set dname='CONSULTING' where deptno=20;
Update dept set Loc='ORLANDO' where deptno=10;
end;
procedure AUTON_LOCK_MAIN(Dname IN OUT VARCHAR2, deptno IN OUT number, Loc IN
OUT VARCHAR2) as
begin
Update dept set Dname='SUPPORT' where deptno=10;
AUTON_LOCK_LOCAL(Dname, deptno, Loc);
update dept set loc='QQQ' where deptno=20;
end;
end AUTON_LOCK;
27 rows selected.
We see from the text print out of the source code for this object that it is an autonomous
transaction.
Now lets recreate this package but modify it slightly placing an commit statement before
and after the call to the LOCAL procedure from the MAIN procedure.
Create or Replace Package AUTON_NO_LOCK as
procedure auton_no_lock_local (Dname IN OUT VARCHAR2, deptno IN OUT number, Loc IN
OUT VARCHAR2);
procedure auton_no_lock_main(Dname IN OUT VARCHAR2, deptno IN OUT number, Loc IN
OUT VARCHAR2);
END AUTON_NO_LOCK; /
show errors
CREATE OR REPLACE PACKAGE BODY AUTON_NO_LOCK AS
PROCEDURE auton_no_lock_local (Dname IN OUT VARCHAR2, deptno IN OUT number, Loc IN
OUT VARCHAR2) as
pragma AUTONOMOUS_TRANSACTION;
begin
Update dept set dname='CONSULTING' where deptno=20;
Update dept set Loc='ORLANDO' where deptno=10;
commit;
end;
procedure auton_no_lock_main(Dname IN OUT VARCHAR2, deptno IN OUT number, Loc IN
OUT VARCHAR2) as
begin
Update dept set Dname='SUPPORT' where deptno=10;
commit;
auton_no_lock_local(Dname, deptno, Loc);
update dept set loc='QQQ' where deptno=20;
end;
end AUTON_NO_LOCK; /
show errors
Now run the procedure using the following:
declare
Dname varchar2(14) :='ACCOUNTING';
deptno number :=10;
Loc varchar2(13) :='New York';
begin auton_no_lock.auton_no_lock_main(Dname, deptno, Loc);
end; /
Note that now there is no problem with locking.
RELATED DOCUMENTS
-----------------
Note:15476.1 FAQ about Detecting and Resolving Locking Conflicts
Note:65961.1 Oracle8i: autonomous Transactions
Note:157885.1 How to COMMIT from a Stored Procedure without Impacting Form Locks
Note:164661.1 Ora-60 And Deadlocks Most Common Causes

Você também pode gostar