1. 程式人生 > >Bitmap index引發的死鎖

Bitmap index引發的死鎖

對於bitmap index,我們知道,同一個值會利用一個位圖來進行索引。假如有如下測試表:

[email protected]>select* from test;
ID NAME
---------- --------------------
1 a
1 b
1 c
2 a
2 b
2 c

那麼在ID列上建bitmap index的話,所有ID=1的會放到一個位圖中,所有ID=2的是另外一個位圖,而在執行DML操作的時候,鎖定的將是整個點陣圖中的所有行,而不僅僅是DML涉及到的行。由於鎖定的粒度變粗,bitmap index更容易導致死鎖的發生。

下面我們利用上面的test作為例子,來演示一下bitmap index導致的deadlock:

1.建立bitmap index

[email protected]>create bitmap index ix_test on test(id);
Index created.

2.在session 1執行

[email protected]>update test set id=3 where id=1 and name='a';
1 row updated.

此時所有id=1的行都被鎖定

3.在session 2執行

[email protected]>update test set id=4 where id=2 and
name='a'; 1 row updated.

此時所有id=2的行都被鎖定

4.在session 1執行

[email protected]>update test set id=4 where id=2 and name='b';

此時會話被阻塞

5.在session 2執行

[email protected]>update test set id=3 where id=1 and name='b';

此時會話被阻塞

6.再回到session 1,發現系統檢測到了死鎖的發生

[email protected]>update test set
id=4 where id=2 and name='b'; update test set id=4 where id=2 and name='b' * ERROR at line 1: ORA-00060: deadlock detected while waiting for resource

相關trace檔案中的記錄:

* SESSION ID:(138.5621) 2007-03-01 10:58:00.187 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-00040001-000000ea 18 138 X 20 134 S TX-0006002d-00000131 20 134 X
18 138 S session 138: DID 0001-0012-00000015 session 134: DID
0001-0014-00000798 session 134: DID 0001-0014-00000798 session 138:
DID 0001-0012-00000015 Rows waited on: Session 134: obj - rowid =
00003199 - AAADGZAAAAAAAAAAAA (dictionary objn - 12697, file - 0,
block - 0, slot - 0) Session 138: obj - rowid = 00003199 -
AAADGZAAAAAAAAAAAA (dictionary objn - 12697, file - 0, block - 0, slot
- 0) Information on the OTHER waiting sessions: Session 134: pid=20 serial=9803 audsid=30524 user: 27/NING O/S info: user:
BEPDG00726-XPAdministrator, term: BEPDG00726-XP, ospid: 2088:4080,
machine: GDCBEPDG00726-XP program: sqlplus.exe application name:
SQL*Plus, hash value=3669949024 Current SQL Statement: update test set
id=4 where id=1 and name=’b’ End of information on OTHER waiting
sessions. Current SQL statement for this session: update test set id=3
where id=2 and name=’b’

死鎖發生的根本原因是對於資源的排他鎖定順序不一致。上面的試驗中,session1對於bitmap index中的2個位圖是先鎖定ID=1的點陣圖,然後請求ID=2的點陣圖,而在此之前ID=2的點陣圖已經被session2鎖定。

session2則先鎖定ID=2的點陣圖,然後請求ID=2的點陣圖,而此前ID=1的點陣圖已經被session1鎖定。於是,session1等待session2釋放ID=2的點陣圖上的鎖,session2等待session1釋放ID=1的點陣圖上的鎖,死鎖就發生了。

而如果我們建立的是普通的B*Tree index,重複上面的試驗則不會出現任何的阻塞和死鎖,這是因為鎖定的只是DML操作涉及到的行,而不是所有ID相同的行。