Verrouille toi à mort moi-même

J’ai rencontré une situation assez unique (quoique!) dans laquelle un programme arrive à générer un deadlock Oracle avec une seule session. Voici l’extrait de la trace du process incriminé :

*** 2011-04-30 07:34:18.590
DEADLOCK DETECTED ( ORA-00060 )

[Transaction Deadlock]

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-00070021-0000022c 33 154 X 33 154 S

session 154: DID 0001-0021-00000011 session 154: DID 0001-0021-00000011

Rows waited on:
Session 154: no row

Remarquez qu’avec tout ce qui m’arrive en ce moment, c’est un vrai bonheur de constater qu’Oracle s’en sort sans une égratignure. Je vais vous expliquer le fin mot de l’histoire…
Où plutôt, voici un script qui arrive à cette situation. Comme vous vous en rendrez compte facilement, la faute à une logique applicative défaillante qui met en oeuvre pragma autonomous_transaction :

create table X(id number primary key);

create or replace procedure ins(p_id number) is
pragma autonomous_transaction;
begin
insert into X values (p_id);
commit;
end;
/

create or replace procedure ins_wtest(p_id number) is
begin
insert into X values (p_id);
ins(p_id);
rollback;
end;
/

exec ins_wtest(1)
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
ORA-06512: at "SYS.INS", line 4
ORA-06512: at "SYS.INS_WTEST", line 4
ORA-06512: at line 1


drop table x purge;
drop procedure ins;
drop procedure ins_wtest;

Ca, c’est fait ; maintenant la suite…