位图索引(bitmap index)冲突引起的TX锁争用
下面做一個測試:
打開一個會話1:
SQL> select sid from v$mystat where rownum<2;
? ? ? ?SID
----------
? ? ? ?148
SQL> create table tx_b(name1 char(10),name2 char(10),name3 char(10));
表已創建。
SQL> create bitmap index tx_b_idx on tx_b(name1,name2,name3);
索引已創建。
SQL> insert into tx_b values('a','b','c');
已創建 1 行。
新打開一個會話2:
SQL> select sid from v$mystat where rownum<2;
? ? ? ?SID
----------
? ? ? ?141
SQL> insert into tx_b values('a','b','c');
一直處于等待狀態
再打開一個會話3:
SQL> select * from v$lock where type='TX'; ?
ADDR ? ? ? ? ? ? ?KADDR ? ? ? ? ? SID ? ?TY ? ? ? ?ID1 ? ? ? ? ? ?ID2 ? ? ? LMODE ? ?REQUEST? ? ?CTIME ? ? ?BLOCK
-------- ? ? ? ? ? ? ?-------- ? ? ? ? ? ?---------- -- ? ? ?---------- ? ---------- ? ---------- ? ? ---------- ? ? ? ? ? ??---------- ----------
6C26DA0C ?6C26DB20 ? ? ? ?141 ? TX ? ? 327684 ? ? ? 3452 ? ? ? ? ?6 ? ? ? ? ? ? 0? ? ? ? ? ? ? ? ? ? ?111 ? ? ? ? ? ?0
6CA63958 ?6CA6396C ? ? ? ?141 ? ? TX ? ? 262181 ? ? ?14897 ? ? ? ? ?0 ? ? ? ? ? ? 4? ? ? ? ? ? ? ? ? ?111 ? ? ? ? ? ?0
6C2953FC ?6C295510 ? ? ? ?148 ? ?TX ? ? 262181 ? ? ?14897 ? ? ? ? ?6 ? ? ? ? ? ? 0? ? ? ? ? ? ? ? ? ? ? 216 ? ? ? ? ?1
這個結果與唯一鍵沖突引起的等待現象完全相同。只通過等待現象,不能區別唯一鍵沖突和位圖索引沖突之間的差異,只有在同時考慮到創建索引的準確信息和sql語句,才能掌握準確的原因。
索引葉節點(leaf node)上發生分割時,相關的等待時間是enq:TX-index contention
B*Tree索引在添加數據的過程中,如果葉節點已滿就會進行分割(split),以此到大平衡,會話A在exclusive模式已獲得TX鎖的情況下,執行分割的過程中,會話B正要修改葉節點時,會話B為了以shared模式獲得會話A擁有的TX鎖只好等待,在此期間會發生enq:TX-index contention等待事件。
一般情況下enq:TX-index contention等待不會發生,它主要是在多個會話對已有索引的表執行較多量的DML時發生。這個等待現象雖然不經常發生,但創建的數量多,組成索引的列值大而指針葉節點的塊頻繁被分割時,成為性能下降的原因,特別是使用sequence等方式生成值的列在創建索引時,一直出現只在最后的葉節點添加值的現象,所以可能經常發生索引分割。這是以排序形式保持葉節點的B*Tree 索引屬性引起的,因此多個會話將大量的數據執行insert 時,與buffer busy waits 等待一起發生enq:TX-index contention等待。
減少索引分割引發的爭用的基本方法,就是阻止在相同的葉節點塊里集中添加數據的現象,例如可以應用partitioning方法進行物理分散,或是修改該組成索引的列的順序而自然分散等方法。單若存在以特定鍵為基準排序這樣的約束條件,就無法使用此方法。具有代表性的情況是利用sequence賦予主鍵值,利用/*INDEX_DESC*/ 之類的提示,對此索引以排序的方式執行掃描數據查詢。通過這種方式使用索引時,必須保障相應鍵為基準排序,所以不能在索引上應用partitioning或修改該索引的列順序。
另一種方法是將索引的塊設定的較大。使用較大的塊時,一個塊上的條目數量多,因此較少發生分割。但是若塊大小增加,就可能引發buffer lock 爭用引起的buffer busy waits 等待現象,所以要謹慎使用。
請注意一點,修改沒有創建索引的表過程中,有時能發生enq:TX-index contention等待。表里有lob列時,就會從內部創建對于LOB數據的索引(稱為LOB索引)因此多個會話同時修改LOB數據時會發生索引爭用。
)其他情況時,相關的等待時間是enq:TX-contention
***分布式事務(distributed transaction)環境下,通過prepared transaction讀取已獲得鎖的行時,知道事務結束為止,為了一shared 模式獲取TX鎖而需要等待。
***將FLM以段空間管理方法使用時,想要分配TFL(transaction free list)的進程無法分配到TFL時,為了一shared 模式獲得已經占有TFL的事務的TX鎖,需要等待。
***回滾段頭的事務表上西藥分配新的slot時,應該以exclusive模式獲得TX鎖。
enq:UL-contention ?PL/SQL lock Timer
使用DBMS_LOCK程序包,可以對任意假想的資源掛起鎖,如果是因為DML發生的鎖時,雖然必須需要物理資源(表,事務,段等),但使用DBMS_LOCK程序包沒有這種限制,使用DBMS_LOCK程序包獲取鎖稱為UL(Userdefined ?Lock)鎖,為了獲得UL鎖 而等待的會話,將發生enq:UL-contention等待事件。
利用DBMS_LOCK.REQUEST函數可以將UL鎖以Exclusive模式獲得,利用DBMS_LOCK.RELEASE函數,可以釋放鎖。記住UL鎖的釋放只能在擁有鎖的會話上實現,若特定會話因長時間擁有UL鎖,而引發并發性問題,則除了強制結束會話之外沒有其他方法。使用DBMS_LOCK.REQUEST函數時,盡量使用RELEASE_ON_COMMIT選項,以避免多余的擁有鎖,使用這個選項若發生提交或回滾,則自動釋放該事務所擁有的UL鎖。
另外,還有一個與DBMS_LOCK程序包相關的等待事件,利用DBMS_LOCK.SLEEP Procedure 暫時中斷事務時,則該進程等待PL/SQL lock timer事件。
PL/SQL lock timer 等待事件不會引起性能的問題。如果該等待時間比預期還要長,就應該重新檢查應用程序的實現邏輯是否有問題。
以下查詢,可以查詢出在位圖索引上的等待事件:
注意:位圖索引在位圖的段級別上(而不是在行級別上)設置鎖。如果對位圖索引中的一列進行更新,行級鎖將會出問題。
總結
以上是生活随笔為你收集整理的位图索引(bitmap index)冲突引起的TX锁争用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习笔记:ORACLE 性能优化求生指南
- 下一篇: 发生TM锁争用的情况