關於一個TX鎖的KILL過程

請將 emp.empno=7369 的記錄 ename 字段修改成「ENMOTECH」並提交,你可能會遇到各類故障,請嘗試解決。面試

其實題目的設計很是簡單,一個 RAC 雙節點的實例環境,面試人員使用的是實例2,而咱們在實例1中使用 select for update 將 EMP 表加鎖:sql

SQL> SELECT * FROM emp FOR UPDATE;數據庫

此時在實例2中,若是執行如下 SQL 語句嘗試更新 ename 字段,必然會被行鎖堵塞:session

SQL> UPDATE emp SET ename='ENMOTECH' WHERE empno=7369;.net

這道面試題中包含的知識點有:設計

1.進程

如何在另一個 session 中查找被堵塞的 session 信息;事件

2.事務

3.get

如何找到產生行鎖的 blocker;

4.

5.

在殺掉 blocker 進程以前會不會向面試監考人員詢問,我已經找到了產生堵塞的會話,是否是能夠kill掉;

6.

7.

在得到能夠 kill 掉進程的確認回覆後,正確殺掉另外一個實例上的進程。

8.

這道題咱們期待能夠在5分鐘以內得到解決,實際上大部分應試者在15分鐘之後都徹底沒有頭緒。

注意:其實Oracle的任何複雜問題處理,均可以是由刪繁就簡的步驟逐層推演出來的,保持清醒的思路,對於DBA的工做很是重要。

正確的思路和解法應該以下:

檢查被阻塞會話的等待事件

更新語句回車之後沒有回顯,明顯是被鎖住了,那麼如今這個會話經歷的是什麼等待事件呢?

能夠經過SESSION等待去獲取這些信息:

SQL> SELECT sid,event,username,SQL.sql_text

2 FROM v$session s,v$sql SQL

3 WHERE s.sql_id=SQL.sql_id

4 AND SQL.sql_text LIKE 'update emp set ename%';

SID EVENT USERNAME

---

79 enq: TX - ROW LOCK contention ENMOTECH

SQL_TEXT

 

UPDATE emp SET ename='ENMOTECH' WHERE empno=7369

以上使用的是關聯 v$sql 的 SQL 語句,實際上經過登陸用戶名等也能夠快速定位被鎖住的會話。

查找 blocker

得知等待事件是 enq: TX – row lock contention,行鎖,接下來就是要找到誰鎖住了這個會話。在10gR2之後,只須要 gv$session 視圖就能夠迅速定位 blocker,經過 BLOCKING_INSTANCE 和 BLOCKING_SESSION 字段便可。

SQL> SELECT SID,INST_ID,BLOCKING_INSTANCE,

BLOCKING_SESSION

FROM gv$session WHERE INST_ID=2 AND SID=79;

SID INST_ID BLOCKING_INSTANCE BLOCKING_SESSION

--- -------

79 2 1 73

上述方法是最簡單的,若是是使用更傳統的方法,實際上也並不難,從 gv$lock 視圖中去查詢便可。

SQL> SELECT TYPE,ID1,ID2,LMODE,REQUEST

FROM v$lock WHERE sid=79;

TY ID1 ID2 LMODE REQUEST

-- ----- -------

TX 589854 26267 0 6

AE 100 0 4 0

TM 79621 0 3 0

SQL> SELECT INST_ID,SID,TYPE,LMODE,REQUEST

FROM gv$Lock WHERE ID1=589854 AND ID2=26267;

INST_ID SID TY LMODE REQUEST

---- --

2 79 TX 0 6

1 73 TX 6 0

乙方DBA需謹慎

第三個知識點是考覈做爲乙方的謹慎,即便你查到了 blocker,是否是應該直接 kill 掉,必需要先徵詢客戶的意見,確認以後才能夠殺掉。

清除blocker

已經確認了能夠 kill 掉 session 以後,須要再找到相應 session的serail#,這是 kill session 時必須輸入的參數。

SQL> SELECT SID,SERIAL# [size=10.5000pt]

FROM gv$session [size=10.5000pt]

WHERE INST_ID=1 AND SID=73;

[size=10.5000pt]

SID SERIAL#[size=10.5000pt]

 

73 15625

若是是 11gR2 數據庫,那麼直接在實例2中加入@1參數就能夠殺掉實例1中的會話,若是是10g,那麼登入實例1再執行 kill session 的操做。

SQL> ALTER system [size=10.5000pt]

KILL SESSION '73,15625,@1';

[size=10.5000pt]

System altered.

再檢查以前被阻塞的更新會話,能夠看到已經更新成功了。

SQL> UPDATE emp SET ename='ENMOTECH' [size=10.5000pt]

WHERE empno=7369;[size=10.5000pt]

1 ROW updated.

對於熟悉整個故障解決過程的人,或者具有清晰思路的DBA,5分鐘以內就能夠解決問題。

深刻一步

對於 TX 鎖,在 v$lock 視圖中顯示的 ID1 和 ID2 是什麼意思? 解釋能夠從 v$lock_type 視圖中獲取。

SQL> SELECT ID1_TAG,ID2_TAG [size=10.5000pt]

FROM V$LOCK_TYPE WHERE TYPE='TX';

[size=10.5000pt]

ID1_TAG ID2_TAG[size=10.5000pt]

[size=10.5000pt]

usn<<16 | slot SEQUENCE

因此 ID1 是事務的 USN+SLOT,而 ID2 則是事務的 SQN。這些能夠從 v$transaction 視圖中得到驗證。

SQL> SELECT taddr

FROM v$session WHERE sid=73;

TADDR

 

000000008E3B65C0

SQL> SELECT XIDUSN,XIDSLOT,XIDSQN

FROM v$transaction

WHERE addr='000000008E3B65C0';

XIDUSN XIDSLOT XIDSQN

 

9 30 26267

如何和 ID1=589854 and ID2=26267 對應呢? XIDSQN=26267 和 ID2=26267 直接就對應了,沒有問題。 那麼 ID1=589854 是如何對應的?將之轉換爲16進制,是 0x9001E,而後分高位和低位分別再轉換爲10進制,高位的16進制9就是十進制的9,也就是 XIDUSN=9,而低位的16進制1E轉換爲10進制是30,也就是 XIDSLOT=30。

文章寫到這裏,突然感受網上那些一鼓作氣的故障診斷腳本其實挺誤人的,只須要給一個參數,運行一下腳本就列出故障緣由。因此不多人願意再去研究這個腳本爲何這麼寫,各個視圖之間的聯繫是如何環環相扣的。因此當你再也不使用本身的筆記本,再也不能迅速找到你賴以生存的那些腳本,你還能一步一步地解決故障嗎?

相關文章
相關標籤/搜索