91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Oracle的死鎖分析

發布時間:2021-11-09 14:22:56 來源:億速云 閱讀:149 作者:iii 欄目:關系型數據庫

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

問題背景描述:

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

--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),指向新的數據塊,如下圖:



    Oracle的死鎖分析

  • 行連接一般是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的死鎖分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

巴林左旗| 团风县| 萨迦县| 梁山县| 南召县| 花垣县| 南阳市| 响水县| 朔州市| 湘乡市| 台南市| 修文县| 抚顺市| 从江县| 乌海市| 邵武市| 梁河县| 柏乡县| 庆元县| 宝丰县| 天峨县| 马尔康县| 灵丘县| 肥西县| 嘉祥县| 随州市| 泌阳县| 普兰店市| 莱西市| 溧阳市| 扎鲁特旗| 河北省| 布拖县| 河南省| 体育| 铜梁县| 涟水县| 崇州市| 藁城市| 邵东县| 西昌市|