oracle鎖阻塞的分析
此文章列舉三個關於鎖阻塞的例子,並對此作詳細的說明,話不多說,直接開題。
一:外來鍵沒有索引,引起阻塞
外來鍵沒有建立索引而引起的阻塞應該是最常見到,下面舉例對此詳細分析
SQL> DELETE EMP WHERE EMPNO=7900;
已刪除1行。
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 458791 1813 6 0 416 0
10 TM 30139 0 3 0 416 0
10 TM 30137 0 2 0 416 0
SQL> select trunc(458791/power(2,16)) ,mod(458791,power(2,16)) from dual;
TRUNC(458791/POWER(2,16)) MOD(458791,POWER(2,16))
------------------------- -----------------------
7 39
再來查v$transaction,看看sid=10會話當前使用的undo segment和slot
SQL> select addr,xidusn,xidslot,xidsqn from v$transaction
2 where addr in (select taddr from v$session where sid=10);
ADDR XIDUSN XIDSLOT XIDSQN
-------- ---------- ---------- ----------
67BAB0CC 7 39 1813
對於tx鎖,v$lock中的id1即為持有該鎖的事務的回滾段號,事務槽號的組合
再來看
SQL> select owner,object_name from dba_objects where object_id in (30139,30137);
OWNER OBJECT_NAME
------------------------------ --------------------------------------------------------------------------------
SCOTT DEPT
SCOTT EMP
對於tm鎖,id1即為持有該鎖的物件的id,結合上一個查詢,可以看到,該會話對30139即emp表加了lmode=3的鎖,即rx鎖,同時,對30137即dept加了lmode=2的鎖,即rs鎖。
接下來在另外一會話中執行如下語句
delete dept where1=0;
該會話被阻塞
檢視v$lock
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 458791 1813 6 0 416 0
10 TM 30139 0 3 0 416 1
10 TM 30137 0 2 0 416 0
12 TM 30139 0 0 4 372 0
12 TM 30137 0 3 0 372 0
可以看到,另一個會話(sid=12)對30137即dept加了lmode=3的鎖,即rx鎖。同時請求對30139即emp表加了lmode=4的鎖,即s鎖(request=4),但該請求被阻塞(s和rx不相容),可以通過id1,id2,,block欄位看到,此會話sid=10會話阻塞。
接下來,在emp的外來鍵欄位deptno建立索引
SQL> create index idx_emp_dept on emp(deptno);
Index created
按原步驟重複上面的實驗
SQL> DELETE EMP WHERE EMPNO=7900;
已刪除1行。
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 196632 2251 6 0 386 0
10 TM 30139 0 3 0 386 0
10 TM 30137 0 2 0 386 0
可以看到,是否建立索引,對emp表的鎖情況沒有影響。
在另外一個會話中執行如下語句
SQL> DELETE DEPT WHERE 1=0;
已刪除0行。
該語句沒有被阻塞,可以執行。看看當前的鎖資訊
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 196632 2251 6 0 435 0
10 TM 30139 0 3 0 435 0
10 TM 30137 0 2 0 435 0
12 TM 30139 0 2 0 9 0
12 TM 30137 0 3 0 9 0
可以看到,在外來鍵上建立索引後,刪除父表,對子表加的是rs鎖,比沒有索引加s的強度要低,這樣避免了阻塞的發生,提高了系統的並行性。
二:點陣圖索引帶來的阻塞
點陣圖索引適合建在低基數列上面,在資料倉儲比較常用,如果是在併發性要求較高的oltp系統就要慎重了,不當的應用,可能會帶來嚴重的阻塞。
SQL> create bitmap index bidx_emp_job on emp(job);
索引已建立。
SQL> DELETE EMP WHERE EMPNO=7369;
已刪除1行。
在另外一會話中執行sql語句
SQL> DELETE EMP WHERE EMPNO=7876;
該語句阻塞
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 524312 2362 6 0 116 1
10 TM 30139 0 3 0 116 0
10 TM 30137 0 2 0 116 0
12 TX 589864 2399 6 0 98 0
12 TM 30139 0 3 0 98 0
12 TM 30137 0 2 0 98 0
12 TX 524312 2362 0 4 98 0
可以看到,sid=12的會話等待sid=10持有的tx鎖,雖然刪除的是不同記錄,但因為
empno等於7876,7369的job欄位值都是’CLERK’,而我們恰恰在job欄位建立了點陣圖索引,第一個dml語句引起了對job=CLERK點陣圖段的鎖定,進而阻塞了第二個會話對該點陣圖段其他記錄的dml操作(注:如此時對job<>CLERK的記錄做dml是不會阻塞的)。
三:Maxtrans帶來的阻塞
在建立一個物件的時候,可以指定initrans,maxtrans引數,這二個引數指定了分配給該物件中每個block初始和最大允許併發事務數的,對每個事務,在其受影響的block內都對應一個itl,受其影響的行都會在行的lock byte(lb)位置此itl號(dump一個dml過的但還沒有commit或者rollback的block可以清楚的看到),如果在一個併發性非常高的系統中,甚至超過了maxtrans的值(或者block的free space用完),那麼oracle就無法增加itl,因此過低的maxtrans同樣會引起sql語句的阻塞。
SQL> drop index bidx_emp_job;
索引已丟棄。
SQL> alter table emp maxtrans 3;
表已更改。
SQL>select distinct dbms_rowid.rowid_relative_fno(rowid) file_id,dbms_rowid.rowid_block_number(rowid) block_id from emp;
FILE_ID BLOCK_ID
---------- ---------
1 50466
所有的記錄都在1號檔案的50466塊,開三個session,分別刪除三條不同的記錄,三個session都可以正常執行,現在再開第四個session,刪除一個不同的記錄,該session被阻塞
一:外來鍵沒有索引,引起阻塞
外來鍵沒有建立索引而引起的阻塞應該是最常見到,下面舉例對此詳細分析
SQL> DELETE EMP WHERE EMPNO=7900;
已刪除1行。
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 458791 1813 6 0 416 0
10 TM 30139 0 3 0 416 0
10 TM 30137 0 2 0 416 0
SQL> select trunc(458791/power(2,16)) ,mod(458791,power(2,16)) from dual;
TRUNC(458791/POWER(2,16)) MOD(458791,POWER(2,16))
------------------------- -----------------------
7 39
再來查v$transaction,看看sid=10會話當前使用的undo segment和slot
SQL> select addr,xidusn,xidslot,xidsqn from v$transaction
2 where addr in (select taddr from v$session where sid=10);
ADDR XIDUSN XIDSLOT XIDSQN
-------- ---------- ---------- ----------
67BAB0CC 7 39 1813
對於tx鎖,v$lock中的id1即為持有該鎖的事務的回滾段號,事務槽號的組合
再來看
SQL> select owner,object_name from dba_objects where object_id in (30139,30137);
OWNER OBJECT_NAME
------------------------------ --------------------------------------------------------------------------------
SCOTT DEPT
SCOTT EMP
對於tm鎖,id1即為持有該鎖的物件的id,結合上一個查詢,可以看到,該會話對30139即emp表加了lmode=3的鎖,即rx鎖,同時,對30137即dept加了lmode=2的鎖,即rs鎖。
接下來在另外一會話中執行如下語句
delete dept where1=0;
該會話被阻塞
檢視v$lock
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 458791 1813 6 0 416 0
10 TM 30139 0 3 0 416 1
10 TM 30137 0 2 0 416 0
12 TM 30139 0 0 4 372 0
12 TM 30137 0 3 0 372 0
可以看到,另一個會話(sid=12)對30137即dept加了lmode=3的鎖,即rx鎖。同時請求對30139即emp表加了lmode=4的鎖,即s鎖(request=4),但該請求被阻塞(s和rx不相容),可以通過id1,id2,,block欄位看到,此會話sid=10會話阻塞。
接下來,在emp的外來鍵欄位deptno建立索引
SQL> create index idx_emp_dept on emp(deptno);
Index created
按原步驟重複上面的實驗
SQL> DELETE EMP WHERE EMPNO=7900;
已刪除1行。
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 196632 2251 6 0 386 0
10 TM 30139 0 3 0 386 0
10 TM 30137 0 2 0 386 0
可以看到,是否建立索引,對emp表的鎖情況沒有影響。
在另外一個會話中執行如下語句
SQL> DELETE DEPT WHERE 1=0;
已刪除0行。
該語句沒有被阻塞,可以執行。看看當前的鎖資訊
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 196632 2251 6 0 435 0
10 TM 30139 0 3 0 435 0
10 TM 30137 0 2 0 435 0
12 TM 30139 0 2 0 9 0
12 TM 30137 0 3 0 9 0
可以看到,在外來鍵上建立索引後,刪除父表,對子表加的是rs鎖,比沒有索引加s的強度要低,這樣避免了阻塞的發生,提高了系統的並行性。
二:點陣圖索引帶來的阻塞
點陣圖索引適合建在低基數列上面,在資料倉儲比較常用,如果是在併發性要求較高的oltp系統就要慎重了,不當的應用,可能會帶來嚴重的阻塞。
SQL> create bitmap index bidx_emp_job on emp(job);
索引已建立。
SQL> DELETE EMP WHERE EMPNO=7369;
已刪除1行。
在另外一會話中執行sql語句
SQL> DELETE EMP WHERE EMPNO=7876;
該語句阻塞
SQL> Select sid,type,id1,id2,lmode,request,ctime,block From v$lock Where Type In ('TM','TX');
SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- ---- ---------- ---------- ---------- ---------- ---------- ----------
10 TX 524312 2362 6 0 116 1
10 TM 30139 0 3 0 116 0
10 TM 30137 0 2 0 116 0
12 TX 589864 2399 6 0 98 0
12 TM 30139 0 3 0 98 0
12 TM 30137 0 2 0 98 0
12 TX 524312 2362 0 4 98 0
可以看到,sid=12的會話等待sid=10持有的tx鎖,雖然刪除的是不同記錄,但因為
empno等於7876,7369的job欄位值都是’CLERK’,而我們恰恰在job欄位建立了點陣圖索引,第一個dml語句引起了對job=CLERK點陣圖段的鎖定,進而阻塞了第二個會話對該點陣圖段其他記錄的dml操作(注:如此時對job<>CLERK的記錄做dml是不會阻塞的)。
三:Maxtrans帶來的阻塞
在建立一個物件的時候,可以指定initrans,maxtrans引數,這二個引數指定了分配給該物件中每個block初始和最大允許併發事務數的,對每個事務,在其受影響的block內都對應一個itl,受其影響的行都會在行的lock byte(lb)位置此itl號(dump一個dml過的但還沒有commit或者rollback的block可以清楚的看到),如果在一個併發性非常高的系統中,甚至超過了maxtrans的值(或者block的free space用完),那麼oracle就無法增加itl,因此過低的maxtrans同樣會引起sql語句的阻塞。
SQL> drop index bidx_emp_job;
索引已丟棄。
SQL> alter table emp maxtrans 3;
表已更改。
SQL>select distinct dbms_rowid.rowid_relative_fno(rowid) file_id,dbms_rowid.rowid_block_number(rowid) block_id from emp;
FILE_ID BLOCK_ID
---------- ---------
1 50466
所有的記錄都在1號檔案的50466塊,開三個session,分別刪除三條不同的記錄,三個session都可以正常執行,現在再開第四個session,刪除一個不同的記錄,該session被阻塞
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24558279/viewspace-752690/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle阻塞(鎖等待)查詢Oracle
- 記一次Oracle死鎖/阻塞排查Oracle
- MYSQL 對錶最大ID 搶加鎖時的阻塞分析MySql
- 一條查詢Oracle中的阻塞鎖(以及阻塞在哪個資料上)的SQLOracleSQL
- 通過11G的V$SESSION來分析鎖阻塞關係Session
- Oracle10g中阻塞鎖查詢更簡單Oracle
- Go 中的阻塞分析Go
- Oracle 阻塞Oracle
- 查殺oracle的阻塞Oracle
- RAC環境中的阻塞 查詢鎖
- ORACLE 死鎖分析過程Oracle
- 併發程式設計之臨界區\阻塞\非阻塞\死鎖\飢餓\活鎖程式設計
- 資料庫鎖表與阻塞資料庫
- 鎖的種類,阻塞,死鎖產生與解決辦法。
- MySQL的共享鎖阻塞會話案例淺析MySql會話
- Oracle死鎖原因產生分析Oracle
- Oracle中查詢阻塞與被阻塞SID的方法Oracle
- [翻譯]:SQL死鎖-阻塞探測SQL
- Redis實現併發阻塞鎖方案Redis
- 模擬RI鎖定導致阻塞的場景
- Oracle中診斷阻塞的sessionOracleSession
- Oracle LOCK內部機制及最佳實踐系列(二)模擬RI鎖定導致阻塞的場景,並分析v$lockOracle
- ANALYZE導致的阻塞問題分析
- Java鎖與非阻塞演算法的效能比較與分析+原子變數類的應用Java演算法變數
- PHP 實現簡單阻塞分散式鎖PHP分散式
- oracle的TM鎖、TX鎖Oracle
- oracle的鎖Oracle
- oracle session阻塞查詢OracleSession
- hanganalyze分析會話阻塞會話
- Oracle中顯示阻塞樹的SQLOracleSQL
- MySQL 由於MDL讀鎖select被阻塞MySql
- Oracle的鎖表與解鎖Oracle
- SQLServer的死鎖分析(1):頁鎖SQLServer
- 自旋鎖、阻塞鎖、可重入鎖、悲觀鎖、樂觀鎖、讀寫鎖、偏向所、輕量級鎖、重量級鎖、鎖膨脹、物件鎖和類鎖物件
- Oracle的TX鎖(行級鎖、事務鎖)Oracle
- Oracle阻塞會話查詢Oracle會話
- Oracle中的鎖Oracle
- ORACLE 鎖的概念Oracle