中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

外鍵上有無索引的影響

發布時間:2020-08-13 05:17:26 來源:ITPUB博客 閱讀:203 作者:數據和云 欄目:關系型數據庫

原文鏈接: https://www.modb.pro/db/22800

摘要:今天在摩天輪上看到一個問題,《oracle外鍵無索引為什么會導致死鎖》,為什么呢? 現在通過一些簡單的案例來測試一下,外鍵索引和鎖的關系。

一、環境模擬

1、創建父表dept,主鍵deptno

SQL> create table dept(deptno number,dname varchar2(20),  2  constraint pk_dept primary key (deptno)  3  );
Table created.
SQL>

2、創建子表emp,主鍵empno,外鍵deptno

SQL> create table emp(empno number,ename varchar2(20),deptno number,  2  constraint pk_emp primary key (empno),  3  constraint fk_deptno foreign key (deptno) references dept (deptno)  4  );
Table created.
SQL>

3、插入數據

SQL> insert into dept select deptno,dname from scott.dept;
4 rows created.
SQL> insert into emp select empno,ename,deptno from scott.emp;
14 rows created.
SQL> commit;Commit complete.SQL> select * from dept;
    DEPTNO DNAME---------- ----------------------------------------
        10 ACCOUNTING
        20 RESEARCH
        30 SALES
        40 OPERATIONS
SQL> select * from emp;
     EMPNO ENAME                                        DEPTNO---------- ---------------------------------------- ----------
      7369 SMITH                                            20
      7499 ALLEN                                            30
      7521 WARD                                             30
      7566 JONES                                            20
      7654 MARTIN                                           30
      7698 BLAKE                                            30
      7782 CLARK                                            10
      7788 SCOTT                                            20
      7839 KING                                             10
      7844 TURNER                                           30
      7876 ADAMS                                            20
      7900 JAMES                                            30
      7902 FORD                                             20
      7934 MILLER                                           10
14 rows selected.
SQL>

二、模擬測試–外鍵無索引

session 1:在子表上插入一條記錄,不提交

SQL> select userenv('sid') from dual;
USERENV('SID')--------------
           170

SQL> insert into emp values(3000,‘xiaoli’,10);
1 row created.
SQL>

session 2:在父表上變更一條記錄,將會被掛起

SQL> select userenv('sid') from dual;
USERENV('SID')--------------
           191
SQL> update dept set deptno=10,dname='AAAAA' where deptno=10;

查詢鎖情況:

select
    mm.addr
  , mm.kaddr
  , mm.sid
  , row_number() over (partition by mm.type,mm.id1,mm.id2 order by mm.lmode desc ,mm.ctime desc) resource_row_number
  , mm.type
  , mm.id1
  , mm.id2
  , decode(mm.lmode, 0, null, 1, 'N', 2, 'SS|RS', 3, 'SX|RX', 4, 'S', 5, 'SSX|SRX', 6, 'X') lmode
  , decode(mm.request, 0, null, 1, 'N', 2, 'SS|RS', 3, 'SX|RX', 4, 'S', 5, 'SSX|SRX', 6, 'X') request--  , mm.ctime
  , lpad(trunc(mm.ctime/60/60),3) || ' Hour '
    || lpad(to_char(trunc(mm.ctime/60) - trunc(mm.ctime/60/60) * 60,'fm09'), 2) || ' Min '
    || lpad(to_char(mm.ctime - trunc(mm.ctime/60)*60,'fm09'), 2) || ' Sec' ctime
  , case when mm.block = 1 and mm.lmode != 0 then 'holder'
         when mm.block = 0 and mm.request != 0 then 'waiter'
         else null end role
  , case when ee.blocking_session is not null then 'waiting for SID '|| ee.blocking_session else null end blocking_session
  , dd.sql_text sql_text
  , cc.event wait_eventfrom
    v$lock mm
  , v$session ee
  , v$sqlarea dd
  , v$session_wait ccwhere mm.sid in (                select nn.sid                from (                  select
                      tt.*
                    , count(1) over (partition by  tt.type,tt.id1,tt.id2) cnt
                    , max(tt.lmode) over (partition by tt.type,tt.id1,tt.id2) lmod_flag
                    , max(tt.request) over (partition by tt.type,tt.id1,tt.id2) request_flag                  from v$lock tt ) nn                where nn.cnt > 1
                  and nn.lmod_flag != 0
                  and nn.request_flag != 0)  and mm.sid = ee.sid(+)  and ee.sql_id = dd.sql_id(+)  and mm.sid = cc.sid(+)order by mm.type, mm.id1, mm.id2,mm.lmode desc ,mm.ctime desc;

外鍵上有無索引的影響

這里我們可以看到:
session 1 正在做DML處理,對于DML處理會在表級鎖?上加上SX模式的鎖。
session 2 在更新主鍵deptno的時候,因為在子表EMP對應的外鍵字段上沒有鎖,因此需要在表級(TM)追加了一個S模式的鎖。
session 2 請求追加S模式的鎖在了TM上,因為SX與S模式的鎖是互斥的,因此session 2 被阻塞而掛起。

session 3:在子表上插入一條記錄,同樣將會被掛起

SQL> select userenv('sid') from dual;
USERENV('SID')--------------
           213
SQL> insert into emp values(3001,'xiaozhang',20);

查詢鎖情況:

select
    mm.addr
  , mm.kaddr
  , mm.sid
  , row_number() over (partition by mm.type,mm.id1,mm.id2 order by mm.lmode desc ,mm.ctime desc) resource_row_number
  , mm.type
  , mm.id1
  , mm.id2
  , decode(mm.lmode, 0, null, 1, 'N', 2, 'SS|RS', 3, 'SX|RX', 4, 'S', 5, 'SSX|SRX', 6, 'X') lmode
  , decode(mm.request, 0, null, 1, 'N', 2, 'SS|RS', 3, 'SX|RX', 4, 'S', 5, 'SSX|SRX', 6, 'X') request--  , mm.ctime
  , lpad(trunc(mm.ctime/60/60),3) || ' Hour '
    || lpad(to_char(trunc(mm.ctime/60) - trunc(mm.ctime/60/60) * 60,'fm09'), 2) || ' Min '
    || lpad(to_char(mm.ctime - trunc(mm.ctime/60)*60,'fm09'), 2) || ' Sec' ctime
  , case when mm.block = 1 and mm.lmode != 0 then 'holder'
         when mm.block = 0 and mm.request != 0 then 'waiter'
         else null end role
  , case when ee.blocking_session is not null then 'waiting for SID '|| ee.blocking_session else null end blocking_session
  , dd.sql_text sql_text
  , cc.event wait_eventfrom
    v$lock mm
  , v$session ee
  , v$sqlarea dd
  , v$session_wait ccwhere mm.sid in (                select nn.sid                from (                  select
                      tt.*
                    , count(1) over (partition by  tt.type,tt.id1,tt.id2) cnt
                    , max(tt.lmode) over (partition by tt.type,tt.id1,tt.id2) lmod_flag
                    , max(tt.request) over (partition by tt.type,tt.id1,tt.id2) request_flag                  from v$lock tt ) nn                where nn.cnt > 1
                  and nn.lmod_flag != 0
                  and nn.request_flag != 0)  and mm.sid = ee.sid(+)  and ee.sql_id = dd.sql_id(+)  and mm.sid = cc.sid(+)order by mm.type, mm.id1, mm.id2,mm.lmode desc ,mm.ctime desc;

外鍵上有無索引的影響

這里我們可以看到:
session 3 需要做DML處理,同樣需要請求SX模式的鎖在TM上,因此它被session 2 在TM上S模式鎖的請求阻塞。

三、模擬測試–外鍵有索引

session 1:

SQL> insert into emp values(3000,'xiaoli',10);
1 row created.
SQL>

session 2:

SQL> update dept set deptno=10,dname='AAAAA' where deptno=10;
1 row updated.
SQL>

這里發現session 2 就沒有被 session 1 所阻塞。

四、結論

1、所有的外鍵上創建索引,避免不必要的死鎖產生。
2、update 父表的語句,盡量避免更新主鍵。

向AI問一下細節

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

AI

马公市| 塘沽区| 若羌县| 民和| 绥宁县| 石门县| 翁源县| 郓城县| 于都县| 札达县| 年辖:市辖区| 邵东县| 阿拉善右旗| 普兰店市| 普安县| 汤原县| 江油市| 唐海县| 武义县| 荔波县| 都安| 梨树县| 涟水县| 麻城市| 仙桃市| 云龙县| 罗甸县| 荆门市| 上犹县| 建宁县| 图木舒克市| 铁岭县| 聂拉木县| 香格里拉县| 左贡县| 田东县| 德清县| 石景山区| 工布江达县| 昭觉县| 鄂托克前旗|