Oracle鎖的一些實驗與技術知識
下面回顧一下為解決前面觸發器死鎖問題所碰到過的知識:
1、Oracle鎖資訊檢視:v$lock
主要欄位含義:
kaddr -> v$session.lockwait
type ->鎖型別,除系統本身的鎖外,我們只要關注TX/TM/UL三種。而UL是使用者自定義的鎖,通常關注度不大。所以只剩下TX和TM兩種。
TX是一種行級鎖,通常以一個事務為單位的形式存在,也就是說並不是若干行被鎖住了就出現若干個TX行級鎖。
SQL> conn scott/tiger;
已連線。
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING00 NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> select * from salgrade;
GRADE LOSAL HISAL
---------- ---------- ----------
1 700 1200
2 1201 1400
3 1401 2000
4 2001 3000
5 3001 9999
SQL> update dept d set d.dname = d.dname || '00' where d.deptno = 10;
已更新 1 行。
SQL> select * from v$lock l where l.type in('TX','TM');
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
67B92964 67B92A70 12 TX 65543 3265 6 0 3 0
67B4E074 67B4E088 12 TM 30137 0 3 0 3 0
SQL> update salgrade s set s.losal = s.losal + 10 where s.grade=1;
已更新 1 行。
SQL> select * from v$lock l where l.type in('TX','TM');
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
67B92964 67B92A70 12 TX 65543 3265 6 0 18 0
67B4E0F8 67B4E10C 12 TM 30142 0 3 0 3 0
67B4E074 67B4E088 12 TM 30137 0 3 0 18 0
從以上實驗可以看出
第一次update dept表的時候就出現了一個TX鎖,另一個TM鎖表示的是鎖定的物件(dept)。
此時對應的ID1就是對應的object_id(v$lock.type='TM'時)。
第二次update salgrade表的時候,出現了兩個TM鎖,因為此時鎖定了兩個物件(dept和salgrade)。
但是,對應的TX鎖卻還是隻有一個。
為什麼第二次明明鎖定了兩行,卻只有一個鎖呢?這是由於實際TX鎖並不是真正意義上的行級鎖,而是事務級的。相面這段話是引用funyucat寫的《Oracle多粒度封鎖機制研究》中的一段話:
TX的本義是Transaction(事務),當一個事務第一次執行資料更改(Insert、Update、Delete)或使用SELECT… FOR UPDATE語句進行查詢時,它即獲得一個TX(事務)鎖,直至該事務結束(執行COMMIT或ROLLBACK操作)時,該鎖才被釋放。所以,一個TX鎖,可以對應多個被該事務鎖定的資料行。(在我們用的時候多是其一個事務,然後SELECT… FOR UPDATE NOWAIT)這段話讓我少走了不少彎路,我一直在追求能夠從v$lock中獲取每行鎖定標識的蹤影。從這裡發現我這個想法是不現實的。
這點從v$session表裡面也可以看出。雖然v$session表有記錄鎖表資訊的四個欄位:
row_wait_obj#
row_wait_file#
row_wait_block#
row_wait_row#
(注:這個四個欄位分別對應了rowid的四個組成資訊:即object_id、relative_fileno、block_number、row_number。
不過這裡需要注意的一點是row_id中的object_id實際上是指user_object中的data_object_id。這點在轉換的時候需要注意。)
但是實際上這裡指的是最後一次鎖定的行的資訊。並不是查詢到當時所有鎖定行的資訊。 這點很重要,直接導致了不能找到這些鎖定行的資訊。
SQL> select s.SID, ta.deptno, o.object_name, ta.rowid
2 from v$session s, dept ta, user_objects o, v$locked_object lo
3 where lo.SESSION_ID = s.SID
4 and lo.OBJECT_ID = o.object_id
5 and dbms_rowid.rowid_object(ta.rowid) = o.data_object_id
6 and o.object_id = s.ROW_WAIT_OBJ#
7 and dbms_rowid.rowid_relative_fno(ta.rowid) = s.ROW_WAIT_FILE#
8 and dbms_rowid.rowid_block_number(ta.rowid) = s.ROW_WAIT_BLOCK#
9 and dbms_rowid.rowid_row_number(ta.rowid) = s.ROW_WAIT_ROW#;
SID DEPTNO OBJECT_NAME ROWID
---------- ---------- --------------------------- --------------------------------------------------
13 10 DEPT AAAHW5AABAAAMUSAAA
sid欄位:指的是當前所在session的id,即v$session.sid
id1/id2欄位:
id1欄位上面已經提到過,當v$lock.type='TM'的時候,id1欄位指的就是object_id。類似資訊也可以從v$locked_object中找到:
SQL> desc v$locked_object;
名稱 是否為空? 型別
----------------------------------------------------- -------- ------------------------------------
XIDUSN NUMBER
XIDSLOT NUMBER
XIDSQN NUMBER
OBJECT_ID NUMBER
SESSION_ID NUMBER
ORACLE_USERNAME VARCHAR2(30)
OS_USER_NAME VARCHAR2(30)
PROCESS VARCHAR2(12)
LOCKED_MODE NUMBER
這個表對應有xidusn、xidslot、xidsqn的資訊,這個可以跟v$transaction表對應的欄位進行關聯。
這三個欄位可以在v$lock.type='TX'的時候換算得到:
xidusn=(id1/65536)
xidslot=mod(id1,65536)
xidsqn=id2
lmode及block欄位:
lmode這個欄位顯示了鎖定的模式:
鎖模式:0(None),1(null),2(row share), 3(row exclusive),4 (share),5(share row exclusive),6(exclusive)
share是指共享鎖(select等)。exclusive是指排他鎖(update/delete/select ...for update(nowait)/)。
通常共享鎖可以多個鎖定(都為s鎖),且不能加x鎖。
而排他鎖則是單個鎖定(x鎖),不能再加其他鎖。
block欄位顯示當前鎖是否阻塞了其他鎖:
0, 未阻塞其他程式;
1, 阻塞了其他程式;
2, 'Global', /* This lock is global, so we can't tell */
當lmode>0且block=1時即表明該表處於死鎖狀態,也就是說當時真鎖定了一行記錄,但同時又阻塞了其他程式,下面一條記錄顯示了死鎖的情況:
SQL> select * from v$lock l where l.type in('TM','TX');
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
67BA143C 67BA1548 10 TX 393255 4314 6 0 81 1
................
已選擇6行。
當發生死鎖後,Oracle會自動解鎖(>9ir1),並提示“等待資源時檢測到死鎖”
SQL> update dept d set d.dname = d.dname || '00' where d.deptno = 10;
已更新 1 行。
SQL> update salgrade s set s.losal = s.losal + 10 where s.grade=1;
update salgrade s set s.losal = s.losal + 10 where s.grade=1
*
ERROR 位於第 1 行:
ORA-00060: 等待資源時檢測到死鎖
自動解鎖後,剛才的blcok=1及lmode>0的情況消失。
另外兩個欄位:
ctime:Time since current mode was granted
request:
Lock mode in which the process requests the lock:
0 - none
1 - null (NULL)
2 - row-S (SS)
3 - row-X (SX)
4 - share (S)
5 - S/Row-X (SSX)
6 - exclusive (X)
--大於0時,表示當前會話被阻塞,其它會話佔有改鎖的模式
以上是關於v$lock檢視的一些欄位說明。另外也涉及到了v$session、v$locked_object等檢視的資訊。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12932950/viewspace-607747/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 短連結的一些技術知識
- oracle的TM鎖、TX鎖知識完全普及Oracle
- Oracle鎖基礎知識Oracle
- Oracle的面試問題——技術知識篇(轉)Oracle面試
- 美團知識圖譜問答技術實踐與探索
- TensorFlow技術解析與實戰 4 基礎知識
- oracle rba一些小知識Oracle
- 乾貨 | 知識圖譜的技術與應用
- [NLP] 知識抽取技術
- 開發Webview的技術,小的技術知識點WebView
- Docker知識進階與容器編排技術Docker
- 知識圖譜——技術與行業應用行業
- 與RabbitMQ有關的一些知識MQ
- 非常硬核的技術知識-CopyOnWrite思想
- Oracle10g的一些基本知識Oracle
- 遊戲技術美術之<技術&美術>知識構成遊戲
- 與CompletableFuture有關的一些知識
- oracle一些內部結構知識Oracle
- 全方位掌握OpenStack技術知識
- 【技術性】OO語言知識
- 藍芽Bluetooth技術小知識藍芽
- 一些常用的 Git 進階知識與技巧Git
- Java與Mysql鎖相關知識總結JavaMySql
- 知識圖譜技術的新成果—KGB知識圖譜介紹
- 有關音訊編碼的知識與技術引數(轉載)音訊
- hive的一些知識Hive
- SAP的一些知識
- Dev 日誌 | 文章《快速體驗知識圖譜 OwnThink》中的技術問題dev
- 入駐第一天,分享自己的工作經驗和技術知識
- 一些小知識
- 實時驗證碼技術可改進生物識別身份驗證
- IAST技術知識-Java環境Agent部署知識乾貨分享ASTJava
- 知識抽取簡述|得物技術
- 幽默:經驗與知識的區別 -Richard Feynman
- Oracle分割槽技術-- interval parition實驗及總結Oracle
- 集智學園知識星空——前端技術實現分析(二)前端
- 集智學園知識星空——前端技術實現分析(一)前端
- 解碼知識圖譜:從核心概念到技術實戰