ITPub博客

首页 > 数据库 > Oracle > 由于oracle自主事务造成的死锁

由于oracle自主事务造成的死锁

原创 Oracle 作者:a960549548 时间:2026-06-12 14:30:04 0 删除 编辑

在Oracle数据库中,自主事务(Autonomous Transaction)是指一个独立于当前事务执行的事务。它可以在不依赖于外部事务的情况下独立提交或回滚,而外部事务的状态不会受到影响。自主事务通常用于日志记录、触发器中的独立操作或需要在当前事务上下文之外执行的任务。

自主事务->single resource的死锁,可以通过查看trace看是否是一个资源会话造成的死锁,如果是,那就是自主事务的原因。

多数死锁都是两个资源争用:

--B10cker(s)  Resource Name  Tx-e€l€aeae-eaeaeaaa  Tx-eeecaead-eaeaeaae  process  --Waiter(s)-  session holds waits  254  259  process session holds waits  259

 

自主事务的是一个 TX- 资源在争用导致的,基本上一个资源争用导致的死锁,就是自主事务引起的:

Resource Name  Tx-eøesaeld-eaeaæ€g  process  --B10cker(s)  session holds waits  191  - -Waiter(s)-  process session holds waits

 

一般来说有自主事务的 process 会有多个 session ,自己一个,自主事务单独创建一个,然后去争夺资源,导致死锁。

实验过程:

创建一个自主事务的存储过程 p2

create or replace procedure p2 is
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   update t2 set object_name=object_name|| '1' where owner= 'SCOTT' ;
   commit ;
END ;
/

 

SQL> update t2 set object_name=object_name|| '1' where owner= 'XDB' ;
  
1168 rows updated.
  
SQL> select distinct object_name from t2 where owner= 'XDB' and rownum<10;
  
OBJECT_NAME
--------------------------------------------------------------------------------
XDB$IMPORT_TT_INFO1
SYS_LOB0000069049C00005$$1
SYS_IL0000069044C00001$$1
XDB$H_INDEX1
XDB$RCLIST_V1
XDB$ROOT_INFO1
XDB$XDB_READY1
SYS_IL0000069049C00005$$1
SYS_LOB0000069044C00001$$1
  
9 rows selected.
  
SQL> exec p2;
  
PL/SQL procedure successfully completed.

 

按道理来说,在 p2 已经 commit 了,接下来的 rollback 是不生效的才对

SQL> rollback ;
  
Rollback complete.

 

但是确实生效了,说明自主事务是自己单独一个会话。

SQL> select distinct object_name from t2 where owner= 'XDB' and rownum<10;
  
OBJECT_NAME
--------------------------------------------------------------------------------
XDB$IMPORT_TT_INFO
XDB$ROOT_INFO
XDB$XDB_READY
SYS_LOB0000069044C00001$$
XDB$RCLIST_V
XDB$H_INDEX
SYS_IL0000069044C00001$$
SYS_IL0000069049C00005$$
SYS_LOB0000069049C00005$$
  
9 rows selected.

 

下面开始演示自主事务造成的死锁情况 ( 就是因为自主事务自己也生成了一个 session ,导致 TX- 争用,所以必须牺牲掉自主事务,让前面的语句可以执行成功,不然极端来说,没有死锁机制的话,就会一直 hang 在那里,

但其实前面的 SQL 做了 commit 的话,也不会产生死锁 ) :

SQL> update t2 set object_name=object_name|| '1' where owner= 'SCOTT' ;
  
6 rows updated.
  
SQL> exec p2;
BEGIN p2; END ;
  
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
ORA-06512: at "TEST.P2" , line 4
ORA-06512: at line 1

 

查看 trace 文件:

Deadlock graph:
                        ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name           process session holds waits  process session holds waits
TX-0005001d-00000369        19     191     X             19     191           X

 

这就厉害了,持有者和等待者都是一样的。但我们去看 SO 就会发现不同之处,一个 process 底下有俩 session ,两个 SO 的 owner 不一样,同样的 TX- 资源被两个 SO 会话持有,因此导致了资源征用。

持有者 mode: X 的 SO 的 owner 是 0xf38ac1b0

SO: 0xef3ee108, type: 56, owner: 0xf38ac1b0, flag: INIT/-/-/0x00 if: 0x3 c: 0x3
        proc=0xf351da98, name = transaction , file=ktccts.h LINE:410, pg=0
       (trans) flg = 0x00000e03, flg2 = 0x00014000, flg3 = 0x00000000, prx = (nil), ros = 2147483647, crtses=0xf38ac1b0
       flg  = 0x00000e03: ALC TRN VUS VID CHG
       flg2 = 0x00014000: IMU IMP
       flg3 = 0x00000000:
       bsn = 0x26ba bndsn = 0x26bd spn = 0x26c8
       efd = 5 rfd = 0 DID:
       file:kta.c lineno:0670
       parent xid: 0x0000.000.00000000
       env [0xef3ee520]: (scn: 0x0000.000e4b24  xid: 0x0005.01d.00000369  uba: 0x00c0103e.00b6.06  statement num=0  parent xid: 0x0000.000.00000000  st-scn: 0x0000.000e4b24  hi-scn: 0x0000.00000000  ma-scn: 0x0000.00000000  flg: 0x00000000)
       cev: (spc = 7518  arsp = 0xef4639e0  ubkds (ubk:tsn: 2 rdba: 0x00c0103e flag:0x8 hdl:(nil) addr:(nil))  useg tsn: 2 rdba: 0x00c000c0
             hwm uba: 0x00c0103e.00b6.06  col uba: 0x00000000.0000.00
             num bl: 1 bk list: 0xef33b7f0)
             cr opc: 0x0 spc: 7518 uba: 0x00c0103e.00b6.06
       Begin scn:0x0000.000e4ae4 uba:0x00c0103e.00b6.01 ts:1658744536[07/25/2022 18:22:16]
       Undo blks: 1 recs: 6
       ccbstg: 0x00000000
       (enqueue) TX-0005001D-00000369    DID: 0001-0013-00000013
       lv: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  res_flag: 0x6
       mode: X, lock_flag: 0x0, lock: 0xef3ee180, res: 0xf3e01160
       own: 0xf38ac1b0, sess: 0xf38ac1b0, proc: 0xf351da98, prv: 0xf3e01170

 

请求者 req: X 的 SO 的 owner 是 0xf38ff2e8

SO: 0xf3902fc0, type: 3, owner: 0xf38ff2e8, flag: INIT/-/-/0x00 if: 0x3 c: 0x3
        proc=0xf351da98, name =call, file=ksu.h LINE:12725, pg=0
       (call) sess: cur f38ac1b0, rec 0, usr f38ac1b0; flg:0 fl2:1; depth:1
       svpt(xcb:(nil) sptn:0x26cb uba: 0x00000000.0000.00)
       ksudlc FALSE at location: 0
         ----------------------------------------
         SO: 0xf3d41cb8, type: 8, owner: 0xf3902fc0, flag: INIT/-/-/0x00 if: 0x1 c: 0x1
          proc=0xf351da98, name =enqueue, file=ksq1.h LINE:380, pg=0
         (enqueue) TX-0005001D-00000369  DID: 0001-0013-00000013
         lv: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  res_flag: 0x6
         req: X, lock_flag: 0x10, lock: 0xf3d41d10, res: 0xf3e01160
         own: 0xf38ac1b0, sess: 0xf38ac1b0, proc: 0xf351da98, prv: 0xf3e01180

 

只要把自主事务的那个存储过程中自主事务给注释了,就不会造成死锁了,因为他们这样就算是一个事务了。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70013625/viewspace-3173615/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE,MySQL 8.0 OCP,PMP,拥有OceanBase OBCP,TiDB PCTP,GoldenDB GDCP等多项认证,ITPUB认证专家,微信公众号:DBA之友。

注册时间:2022-02-08

  • 博文量
    132
  • 访问量
    171518