【江枫】一个复杂的死锁案例

上一篇 / 下一篇  2008-04-18 13:08:51

今天被一位朋友问到一个比较复杂的死锁,觉得有点意思,记录一下。数据库版本9206,死锁产生的trace文件包含如下信息:

Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-00090006-0002a8de        91     105     X             69      60           S
TX-0004002a-0002a7cb        69      60     X             91     105           S
session 105: DID 0001-005B-000001DD session 60: DID 0001-0045-00000077
session 60: DID 0001-0045-00000077 session 105: DID 0001-005B-000001DD
Rows waited on:
Session 60: obj - rowid = 000029E8 - AAANTUAAFAAAAAAAAA
  (dictionary objn - 10728, file - 5, block - 0, slot - 0)
Session 105: obj - rowid = 00002829 - AAANTVAAFAAAAAAAAA
  (dictionary objn - 10281, file - 5, block - 0, slot - 0)

导致死锁的两条sql,一条是session 105的insert,一条是session 60的update。

很明显,这不是数据行死锁,因为报出来的rowid中block为0,而且等待的是S锁,那么最有可能的是位图索引导致的死锁。然而很多情况下,位图索引死锁发生在同一个位图索引中,这里却有两个不同的obj:10728和10281。经过询问,这两个对象一个是位图索引,一个是B*tree索引,而且基于不同的列:

10728:
CREATE BITMAP INDEX WATOOL.SRV_PARTSINSTOCK_M_IND6 ON WATOOL.SRV_PARTSINSTOCK_M
(CRITERQTYINSTOCK, REMAINSUM, DELETEFLAG, BOSUM)
NOLOGGING

10281:
CREATE INDEX WATOOL.SRV_PARTSINSTOCK_M_IND3 ON WATOOL.SRV_PARTSINSTOCK_M
(DEALERCODE, PARTSCODE)
LOGGING

奇怪的是这里的B*Tree Index不是唯一索引,应该不会阻塞insert语句,也就不会产生上述的死锁。再问是不是有基于这个index的唯一约束存在,果然有如下主键:

ALTER TABLE SRV_PARTSINSTOCK_M ADD (
  CONSTRAINT SRV_PARTSINSTOCK_M_PK PRIMARY KEY (DEALERCODE, MAKERTYPE, PARTSCODE)
    USING INDEX
    TABLESPACE USERS;

到这里,死锁产生的原因基本上清楚了,B*Tree上的唯一约束阻塞insert,bitmap阻塞update,然后两个语句互相请求对方索引的某行被锁定的数据,导致了死锁的产生。

关于位图索引导致的死锁的原理,可以参考piner的文章

--EOF--


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

我的栏目

日历

« 2008-07-09  
  12345
6789101112
13141516171819
20212223242526
2728293031  

数据统计

  • 访问量: 9996
  • 日志数: 110
  • 建立时间: 2008-03-27
  • 更新时间: 2008-06-24

RSS订阅

Open Toolbar