1. 程式人生 > 實用技巧 >檢視Oracle DB Lock及快速處理 - 後續

檢視Oracle DB Lock及快速處理 - 後續

前情回顧

在上一篇中,我們執行了一個 update 語句,但是卻被 block 住了,經過一番查詢,發現是另一個人也在 update 同一個表,但是沒有 commit 。

修改也很簡單, commit 一下即可。

新的問題

我們有一個 Loader 模組,其作用是把資料從檔案寫入到資料庫表中。

最終,執行的語句是這樣的:

insert /*+ APPEND PARALLEL(4) */ into BIG_TABLE_A ...

在測試中,起了兩個例項,但是,卻發現 L1 阻塞住了 L2 。

分析

問題來了:為什麼都是 insert 語句,一個會 block 住另一個呢?

按照我對於 Oracle 的認知,事務的預設隔離級別是 READ_COMMITTED 已提交讀。寫的時候加行級共享鎖 RS ,直到事務結束才釋放。
對應到這裡,兩個模組 L1 和 L2 其 insert 的內容獨立,各自加行級共享鎖的話,應該是互不影響的,怎麼會發生阻塞呢?

首先,我們通過上一篇的檢視鎖的SQL,可以查詢得知:

L1 SID(800) is blocking L2 SID(900)

所以,我們需要看看 SID=800 這個執行緒,到底 block 在哪裡。

Lock Mode

查詢這個鎖的 Lock Mode :

SELECT * FROM V$ENQUEUE_LOCK where sid = 800;

在結果中,可以看到有一列 LMODE = 6
表明, L1 使用的是 exclusive lock ,即鎖全表。所以發生了阻塞。

進一步查詢資料可知:兩種情況可能進入 Exclusive Lock Mode:

  1. 建立索引
  2. 使用多執行緒直接插入

如下:

Value   Name(s)                    Table method (TM lock)
    0   No lock                    n/a
 
    1   Null lock (NL)             Used during some parallel DML operations (e.g. update) by
                                   the pX slaves while the QC is holding an exclusive lock.
 
    2   Sub-share (SS)             Until 9.2.0.5/6 "select for update"
        Row-share (RS)             Since 9.2.0.1/2 used at opposite end of RI during DML until 11.1
                                   Lock table in row share mode
                                   Lock table in share update mode
 
    3   Sub-exclusive(SX)          Update (also "select for update" from 9.2.0.5/6)
        Row-exclusive(RX)          Lock table in row exclusive mode
                                   Since 11.1 used at opposite end of RI during DML
 
    4   Share (S)                  Lock table in share mode
                                   Can appear during parallel DML with id2 = 1, in the PX slave sessions
                                   Common symptom of "foreign key locking" (missing index) problem
                                   Note that bitmap indexes on the child DON'T address the locking problem
 
    5   share sub exclusive (SSX)  Lock table in share row exclusive mode
        share row exclusive (SRX)  Less common symptom of "foreign key locking" but likely to be more
                                   frequent if the FK constraint is defined with "on delete cascade."
 
    6   Exclusive (X)              Lock table in exclusive mode
                                   create index    -- duration and timing depend on options used
                                   insert /*+ append */ 

第一種情況很很好理解,插入一條資料且需要建立索引的時候, table (理論上)可以只加行級鎖,互不干擾。但是對於 index 來說,
L1/L2 各自的資料是相對連貫的,二叉樹的插入和平衡比較快,但是如果交替進行,效率可能就不高。所以只能使用互斥鎖,一個一個來。

第二種情況,Oracle的文件裡面寫到: direct-load INSERT ,需要在 table 級別使用 exclusive locks 。

In direct-load INSERT, exclusive locks are obtained on the table (or on all the partitions of a partitioned table) precluding any concurrent insert, update, or delete on the table. Concurrent queries, however, are supported and will see only the data in the table before the INSERT began. These locks also prevent any concurrent index creation or rebuild operations. This must be taken into account before using direct-load INSERT because it affects table concurrency.

參考 -> https://docs.oracle.com/cd/A87860_01/doc/server.817/a76965/c21dlins.htm

Lock Object

我們進一步看看 lock 的 object 是啥。

SELECT C.SID WAITER_SID, A.OBJECT_NAME, A.OBJECT_TYPE
FROM DBA_OBJECTS A, V$SESSION B, V$SESSION_WAIT C
WHERE (A.OBJECT_ID = B.ROW_WAIT_OBJ# OR
    A.DATA_OBJECT_ID = B.ROW_WAIT_OBJ#)
AND B.SID = C.SID
AND B.SID = 800
;

結果如下:

WAITER_SID    OBJECT_NAME          OBJECT_TYPE
800	      INDX_BIG_TABLE_A	   INDEX PARTITION

果然,是鎖在 index 上。

解決

原有大概知道了,那怎麼辦呢?

  1. 等。
  2. 把一個低優先順序的 session 停掉,讓另一個先跑。

參考