久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Oracle的死鎖分析

143次閱讀
沒有評論

共計 4124 個字符,預計需要花費 11 分鐘才能閱讀完成。

這篇文章主要介紹“Oracle 的死鎖分析”,在日常操作中,相信很多人在 Oracle 的死鎖分析問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Oracle 的死鎖分析”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!

問題背景描述:

發生死鎖的多個進程執行的都是同一個存儲過程,大概代碼及順序如下:

--1. 首先通過主鍵 order_no 鎖住一條訂單
select t.* from order t where t.order_no= order_no  for update; 
--2. 其次通過主鍵 channel_id 鎖住一個渠道
select t.* from channel t where t.channel_id= channel_id  for update; 
--3. 然后通過主鍵 order_no 對訂單表數據進行修改
update order t set t.order_status=0,t.finish_time=sysdate where t.order_no= order_no 
commit;

死鎖情況描述

session A

-- 正在執行語句 3,他處于 enq: TX - allocate ITL entry 等待
update order t set t.order_status=0,t.finish_time=sysdate where t.order_no= orderno_a

session B

-- 正在執行語句 2,他處于 enq: TX - row lock contention 等待
select t.* from channel t where t.channel_id= ch2  for update;

session C

-- 正在執行語句 2,他處于 enq: TX - row lock contention 等待
select t.* from channel t where t.channel_id= ch2  for update;

可能還會有更多的 session 處于執行語句 2,并等待 enq: TX – row lock contention 的情況,這里暫時只列 3 個 session,其實 2 個也夠了,也能形成,只是概率很低。

等待鏈
A 被 C 堵塞,C 被 B 堵塞,B 被 A 堵塞

等待鏈分析:
A 執行到語句 3 了,說明主鍵為 orderno_a 的 order 數據行鎖和 ch2 的 channel 數據行鎖已經獲取到了,而其余的 B 和 C 只能等待該 ch2 數據的行鎖釋放。
B 和 C 都執行到語句 2 了,說明他們都獲取到了各自的 order 數據行鎖,且數據不是 orderno_a 所代表的數據。這點毋庸置疑。

疑問:A,B,C 操作的都是不同的訂單數據行,且都獲取到了各自的行鎖的,為什么在表 order 上,還會發生 A 被 C 堵塞呢。

要知道為什么有這個疑問,就要先明白,在 A 執行 order 的 for update 時是已經獲取了 itl 資源的,所以在后來真正 update 數據時是不應該存在這個等待的 enq: TX – allocate ITL entry,因為他已經獲取這個資源了。

死鎖分析

要分析這個死鎖就要明白等待事件 enq: TX – allocate ITL entry 所代表的資源 itl 事務槽的含義。itl 事務槽是數據塊頭中用來標記事務的記錄。在這里有個重點是數據塊。想一想,如果事務跨數據塊了會怎樣。這就是這個死鎖的關鍵點。當然不同表的事務肯定跨數據塊了,一個事務即使修改一個表的多條數據也可能跨塊了。這里的情況是,order 表上事務都是通過主鍵來操作的,對于一條數據,要跨越數據塊,行遷移或者行連接會有這種情況。

行遷移一般是 update 后經常出現,比如一個 err_mesg 字段,初期只有 10 個字符,后面 update 為 1000 個字符,如果這個時候原數據塊裝不下了,他就會找另外的數據塊來存放,而原數據塊上放一個新數據塊的 dba(data block address),指向新的數據塊,如下圖:

行連接一般是 insert 時出現的,比如一條數據非常大,大到一個塊裝不下了,oracle 會拆分成多個塊來存放。可以通過創建塊尺寸小的表空間來測試。

到此處,要明白 itl 是數據塊上的資源,即使是同一個事務中,如果事務跨數據塊了,當他要修改這個數據塊時,他也需要重新再次在這個新塊上申請 itl 資源,也就是我這里死鎖中,假設 orderno_a 數據 rowid 指向的塊為 dba_1,行遷移中指向的塊為 dba_2, 在最開始 for update 時獲取的是塊 dba_1 中的 itl 資源,當最后真正 update 數據時,為了保護操作,需要獲取 dba_2 上的 itl 資源。而此時,其余的很多 session,比如 B,C……N 等等 session 將塊 dba_2 上的 itl 資源耗盡了,那么 session A 就處于等待數據塊 dba_2 上的 itl 資源的狀態,對應于 enq: TX – allocate ITL entry。而其他 session 將等待 session A 釋放渠道表數據的鎖。完成了鎖的閉環

到此死鎖分析完畢。

可以使用以下代碼來做簡單的測試

-- 創建 order 表,將 PCTFREE 置為 0,INITRANS 置為 1create table t_order(mesg varchar2(4000)) PCTFREE 0 INITRANS 1;
-- 創建 channel 表
create table t_channel(id NUMBER);-- 準備數據,對于 order 表,至少要有兩個塊有數據
-- 第一個塊的數據,有三條,即 a,b,c
insert into t_order select rpad(a ,3000, a) from dual;
insert into t_itl select rpad(b ,1000, b) from dual;
insert into t_order select rpad(c ,3000, c) from dual;
-- 更改數據 b,此時第一個塊裝不下,將會發生行遷移
update t_order set mesg=(select rpad( b ,3000, b) from dual) where mesg like  b% 
-- 可以使用以下語句分析行遷移的表,只用作測試,在線生產慎用, 可以 dump 第一個數據塊找到,遷移到哪一個 dba 去了
create table CHAINED_ROWS ( owner_name varchar2(30),
 table_name varchar2(30),
 cluster_name varchar2(30),
 partition_name varchar2(30),
 subpartition_name varchar2(30),
 head_rowid rowid,
 analyze_timestamp date
analyze table t_order list chained rows;
select * from CHAINED_ROWS;
-- 繼續插入數據,將遷移后的數據塊數據增加,方便之后 for update 時消耗這個塊的 itl 資源
-- 通常情況,下面插入的數據就是放在 b 數據遷移后的數據塊的
insert into t_order select rpad(d ,1000, d) from dual;
insert into t_order select rpad(f ,6000, f) from dual;
insert into t_order select rpad(g ,300, g) from dual;
insert into t_order select rpad(h ,100, h) from dual;
/* 開始模擬死鎖 */
--t1 時刻
 --session A 
 select * from t_order where mesg like  b%  for update;
 select * from t_channel where id=1 for update;
 --t2 時刻
 --session B
 select * from t_order where mesg like  d%  for update;
 select * from t_channel where id=1 for update;-- 等待 session A  釋放
 -- 其余 session
 select * from t_order where mesg like  f%  for update;
 select * from t_channel where id=1 for update;-- 加入該條數據的行鎖等待
 select * from t_order where mesg like  g%  for update;
 select * from t_channel where id=1 for update;-- 加入該條數據的行鎖等待
 .....
/* 如果這些數據不在 b 所在的塊,可以通過設置 where 條件為以下內容來指定更改 b 遷移后的塊
where DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) =  block_no  
 and DBMS_ROWID.ROWID_ROW_NUMBER(ROWID) = 1;
-- 此時 session B 與其余 session 將 t_order 的第二個塊,即 d,f,g,h 數據所在的塊的 itl 耗盡
--t3 時刻
 --session A  去更改 t_order 的數據
 update t_order t set t.mesg= bbbbb  where t.mesg like  b% 
 -- 此時會等待 session B 及其他 session 釋放 itl 資源,而 session B 及其他 session 又在等待 session A 釋放 channel 的鎖
 -- 形成了互相等待,閉環,死鎖形成 

到此,關于“Oracle 的死鎖分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-24發表,共計4124字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 陇川县| 泽普县| 镇平县| 齐河县| 余庆县| 衡山县| 安化县| 鸡东县| 安宁市| 襄垣县| 繁昌县| 福海县| 微山县| 锦州市| 大同市| 广南县| 阳信县| 敦煌市| 苍梧县| 静宁县| 江川县| 林甸县| 关岭| 兴宁市| 天水市| 确山县| 当阳市| 蒲城县| 措勤县| 马边| 屏边| 原阳县| 石城县| 万全县| 河池市| 老河口市| 南宫市| 三门峡市| 崇信县| 磐安县| 辉县市|