程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle教程 >> ORACLE外鍵和鎖,ORACLE

ORACLE外鍵和鎖,ORACLE

編輯:Oracle教程

ORACLE外鍵和鎖,ORACLE


在oracle中,如果外鍵未加索引,對父表的修改,會導致子表被加上全表鎖。這包括兩種情況:

1.刪除父表中的行,如果外鍵上沒有索引,會導致子表被加上全表鎖

2.更新父表的主鍵(根據關系數據庫的原則,更新主鍵是一個巨大的”禁忌”,所以一般不會出現這種情況),如果外鍵上沒有索引,會導致子表被加上全表鎖

雖然,在Oracle9i及以上的版本中,這些全表鎖都是短期的,他們僅在DML操作期間存在,而不是在整個事務的期間都存在。但是即使如此,這些全表鎖還是可能(而且確實會)導致很嚴重的鎖定問題。

可以通過如下語句,查詢是否存在未加索引的外鍵:

SELECT TABLE_NAME,
       CONSTRAINT_NAME,
       CNAME1 || NVL2(CNAME2, ', ' || CNAME2, NULL) ||
       NVL2(CNAME3, ', ' || CNAME3, NULL) ||
       NVL2(CNAME4, ', ' || CNAME4, NULL) ||
       NVL2(CNAME5, ', ' || CNAME5, NULL) ||
       NVL2(CNAME6, ', ' || CNAME6, NULL) ||
       NVL2(CNAME7, ', ' || CNAME7, NULL) ||
       NVL2(CNAME8, ', ' || CNAME8, NULL) COLUMNS
  FROM (SELECT B.TABLE_NAME,
               B.CONSTRAINT_NAME,
               MAX(DECODE(POSITION, 1, COLUMN_NAME, NULL)) CNAME1,
               MAX(DECODE(POSITION, 2, COLUMN_NAME, NULL)) CNAME2,
               MAX(DECODE(POSITION, 3, COLUMN_NAME, NULL)) CNAME3,
               MAX(DECODE(POSITION, 4, COLUMN_NAME, NULL)) CNAME4,
               MAX(DECODE(POSITION, 5, COLUMN_NAME, NULL)) CNAME5,
               MAX(DECODE(POSITION, 6, COLUMN_NAME, NULL)) CNAME6,
               MAX(DECODE(POSITION, 7, COLUMN_NAME, NULL)) CNAME7,
               MAX(DECODE(POSITION, 8, COLUMN_NAME, NULL)) CNAME8,
               COUNT(*) COL_CNT
          FROM (SELECT SUBSTR(TABLE_NAME, 1, 30) TABLE_NAME,
                       SUBSTR(CONSTRAINT_NAME, 1, 30) CONSTRAINT_NAME,
                       SUBSTR(COLUMN_NAME, 1, 30) COLUMN_NAME,
                       POSITION
                  FROM USER_CONS_COLUMNS) A,
               USER_CONSTRAINTS B
         WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
           AND B.CONSTRAINT_TYPE = 'R'
         GROUP BY B.TABLE_NAME, B.CONSTRAINT_NAME) CONS
 WHERE COL_CNT > ALL (SELECT COUNT(*)
          FROM USER_IND_COLUMNS I
         WHERE I.TABLE_NAME = CONS.TABLE_NAME
           AND I.COLUMN_NAME IN (CNAME1,
                                 CNAME2,
                                 CNAME3,
                                 CNAME4,
                                 CNAME5,
                                 CNAME6,
                                 CNAME7,
                                 CNAME8)
           AND I.COLUMN_POSITION <= CONS.COL_CNT
         GROUP BY I.INDEX_NAME)

這個腳本將最多處理8列外鍵約束(如果你的外鍵有更多的列,可能就得重新考慮一下你的設計了)!

除了全表鎖外,在以下情況下,未加索引的外鍵也可能帶來問題:
     1.如果有on delete cascade,而且沒有對子表加索引:例如,emp是dept的子表,delete deptno=10應該cascade(級聯)至emp。如果emp中的deptno沒有索引,那麼刪除dept表中的每一行時都會對emp做一次全表掃描。這個全表掃描可能是不必要的,而且如果從父表刪除多行,父表中每刪除一行就要掃描儀一次子表。

2.從父表查詢子表:在此考慮emp/dept例子。利用deptno查詢emp表是相當常見的。如果頻繁地運行以下查詢,你就會發現沒有索引會使查詢速度變慢:

select *
     from dept, emp
    where emp.deptno=dept.deptno 
      and dept.deptno=:x;

所以,要特表注意是否需要對外鍵加索引,防止出現這種Oracle“過分地鎖定了”數據的情況。

 

                                                                                                                                                        --參考自《Oracle專家高級編程》


ORACLE的外鍵約束是否必要

主要論點如下記得我不止一次在這裡和別人爭過這個問題了。1. 你的程序再嚴謹也有可能出現BUG;你自己判斷不如交給數據庫判斷,它做得又快又好。大多數人的程序沒有考慮並發問題。一旦考慮了就得手工加鎖,效率很低。數據可能繞過你的應用程序進入數據庫。一個外鍵判斷分攤到事務級別,開銷可以忽略,用戶完全沒有察覺。如果是批量導入數據,可以先暫時屏蔽外鍵,事後用NOVALIDATE選項快速恢復,前提是你的數據是干淨的。外鍵約束正是為了防止你亂來,這是給你的保護。開車系安全帶麻煩吧?有時候它能救你的命。此外,外鍵還會給CBO提供重要的信息,用來生成最優計劃。反方:代表人物qingyun。主要論點如下我不太喜歡外鍵,原因:1.程序邏輯,完整性,我會在存儲過程或包等地方做嚴謹的判斷;2.性能問題,這是我最不喜歡用的關鍵原因,比如一個業務流水表,頻繁插入數據,如果這個表身上有3外鍵,那麼每次插入一條,就必須對這3個外鍵對應的 3個表做相應的查找判斷有無對應數據,如果這3個表也很大,那就這3個表的判斷時間就很常,雖然外鍵指向的關聯表的字段肯定是索引,但是我覺得很多時候,這樣的判斷本來就在程序裡控制好了,通過外鍵再判斷一次,就是降低性能;而且其實有的地方判不判斷也無所謂的,但是用了外鍵,就必須化時間去判斷,無論 oracle內部多麼優化外鍵對於數據的檢索速度,它總是一個不小的消耗;3.維護麻煩,很多公司的軟件都是定制的,這種定制的東西,隨意性相對較大,項目開發實施過程中,需要經常對表修修補補;還有就是業務邏輯有bug或者其他情況,需要經常手工維護數據,有錯綜復雜的外鍵關聯著,很是麻煩;4.外鍵定死了兩個表之間數據的先後生成關系,最常見的是單據主從表,有的時候,在生成單據的時候,是先生成明細,再生成主表;如果釘死了外鍵,這個就沒法實現;當然有些關鍵的業務,確實需要外鍵;比如這個數據庫一共100個表,按他們的想法,外鍵就可能有300個;我暈,太教條主義了;如果說讓我建300個索引,我很樂意,因為提高運作效率的,而外鍵只是檢測嚴謹性,對數據庫的運作效率只有降低,沒有任何提高的可能性;其實這只是設計習慣的問題 ,有興趣大家隨便聊聊自己的習慣。還有一個反方的聲音有獨特見解,一起放上來供大家參考外鍵是暴露的,程序是封閉的,同樣是經過測試的程序和外鍵約束,人為因素造成約束失效的可能性誰大誰小,很明顯,所以反對使用外鍵,因為與系統高可用性目的沖突 哇,太悲劇了。裡面說到newkid 正在做證券軟件。不過他還沒開始動手。但是我們公司就是做證券軟件的,裡面表就是沒有外鍵。哈哈哈
 

oracle的外鍵怎使用?

1、外鍵是屬於約束的一種,所謂約束顧名思義,就是限制你在數據庫的操作。而你對數據庫有什麼操作,無非是增、刪、改、查,外鍵起的作用就是讓你在數據庫幫助的情況下更合理的增加數據的正確度。

2、所以,外鍵只是輔助,並不能起到你說的【B.NAME是否也自動出現張三兩個字】。

3、外鍵的作用是能夠避免如下情況。

【班級信息表】存放的是班級信息表。
【學生表】存放的是學生信息,包含班級信息。

這個時候 在【學生表】中存放的班級信息應該在【班級信息表】存在才合法,自己人為控制的話難免有漏掉的情況,用外鍵則可以讓數據庫自動控制,當插入【學生表】中的數據在【班級信息表】不存在的時候,數據庫不允許插入。

---
以上,希望對你有所幫助。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved