首页 > 数据库 > Oracle > 由于oracle自主事务造成的死锁
在Oracle数据库中,自主事务(Autonomous Transaction)是指一个独立于当前事务执行的事务。它可以在不依赖于外部事务的情况下独立提交或回滚,而外部事务的状态不会受到影响。自主事务通常用于日志记录、触发器中的独立操作或需要在当前事务上下文之外执行的任务。
自主事务->single resource的死锁,可以通过查看trace看是否是一个资源会话造成的死锁,如果是,那就是自主事务的原因。
多数死锁都是两个资源争用:
自主事务的是一个 TX- 资源在争用导致的,基本上一个资源争用导致的死锁,就是自主事务引起的:
一般来说有自主事务的 process 会有多个 session ,自己一个,自主事务单独创建一个,然后去争夺资源,导致死锁。
实验过程:
创建一个自主事务的存储过程 p2
create
or
replace
procedure
p2
isPRAGMA 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_INFO1SYS_LOB0000069049C00005$$1SYS_IL0000069044C00001$$1XDB$H_INDEX1XDB$RCLIST_V1XDB$ROOT_INFO1XDB$XDB_READY1SYS_IL0000069049C00005$$1SYS_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_INFOXDB$ROOT_INFOXDB$XDB_READYSYS_LOB0000069044C00001$$XDB$RCLIST_VXDB$H_INDEXSYS_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
resourceORA-06512:
at
"TEST.P2"
, line 4ORA-06512:
at
line 1 |
查看 trace 文件:
Deadlock graph:
---------Blocker(s)-------- ---------Waiter(s)---------Resource
Name
process session holds waits process session holds waitsTX-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/ ,如需转载,请注明出处,否则将追究法律责任。