父表、子表 主外鍵關系


 

 

ORACLE官方文檔介紹:

Concurrency Control, Indexes, and Foreign Keys

You almost always index foreign keys. The only exception is when the matching unique or primary key is never updated or deleted.(你總是需要對 外鍵添加索引! 唯一的例外就是:匹配的主鍵列 或是 唯一列 從不進行更新操作或者 刪除操作)

Oracle maximizes the concurrency control of parent keys in relation to dependent foreign key values. You can control what concurrency mechanisms are used to maintain these relationships, and, depending on the situation, this can be highly beneficial. The following sections explain the possible situations and give recommendations for each.

No Index on the Foreign Key

Figure 21-8 illustrates the locking mechanisms used by Oracle when no index is defined on the foreign key and when rows are being updated or deleted in the parent table. Inserts into the parent table do not require any locks on the child table.

(當子表外鍵上沒有索引時,對父表做 刪除、更新操作時,會鎖定子表。插入操作不需要 鎖定子表)

Unindexed foreign keys cause DML on the primary key to get a share row exclusive table lock (also sometimes called a share-subexclusive table lock, SSX) on the foreign key table. This prevents DML on the table by other transactions. The SSX lock is released immediately after it is obtained. If multiple primary keys are updated or deleted, the lock is obtained and released once for each row.

Note:

See Also:

"DML Locks"

Figure 21-8 Locking Mechanisms When No Index Is Defined on the Foreign Key

 

 

Description of "Figure 21-8 Locking Mechanisms When No Index Is Defined on the Foreign Key"

Index on the Foreign Key

Figure 21-9 illustrates the locking mechanisms used when an index is defined on the foreign key, and new rows are inserted, updated, or deleted in the child table.

Indexed foreign keys cause a row share table lock (also sometimes called a subshare table lock, SS). This prevents other transactions from exclusive locking the whole table, but it does not block DML on the parent or the child table.

This situation is preferable if there is any update or delete activity on the parent table while update activity is taking place on the child table. Inserts, updates, and deletes on the parent table do not require any locks on the child table, although updates and deletes will wait for row-level locks on the indexes of the child table to clear.

Figure 21-9 Locking Mechanisms When Index Is Defined on the Foreign Key


Description of "Figure 21-9 Locking Mechanisms When Index Is Defined on the Foreign Key"

If the child table specifies ON DELETE CASCADE, then deletes from the parent table can result in deletes from the child table. In this case, waiting and locking rules are the same as if you deleted yourself from the child table after performing the delete from the parent table.

 

 

 

 

 

 

 

 

 

 

 

 

 

子表的外鍵 字段沒有 索引!!!

 

創建測試環境

TEST @ prod >create table father as select * from scott.dept;

 

Table created.

 

TEST @ prod >create table childen as select * from scott.emp;

 

Table created.

 

TEST @ prod >alter table father add constraint pk_deptno primary key (deptno);

 

Table altered.

 

TEST @ prod >alter table childen add constraint fk_deptno foreign key (deptno) references father(deptno);

 

Table altered.

 

此時子表外鍵 不加索引

 

 

 

查鎖語句

創建腳本 chk_lock.sql,利用游標查詢被鎖定的對象lock的模式

[oracle@cuug ~]$ vi chk_lock.sql

declare

v1 lock_more%rowtype;

cursor c1 is select lk.sid,lk_obj.object_id,obj.object_name,DECODE(LK.LMODE,0,'None',1,'Null',2,'Row-S (SS)',3,'Row-X (SX)',4,'Share',5,'S/Row-X (SSX)',6,'Exclusive') lmode

from v$locked_object lk_obj,dba_objects obj,v$lock lk

where lk.sid=lk_obj.session_id and lk_obj.object_id=obj.object_id and lk.sid=154;

begin

open c1;

loop

fetch c1 into v1;

exit when c1%notfound;

insert into lock_more values(v1.locker_sid,v1.locked_objno,v1.locked_obj,v1.lock_mode);

commit;

end loop;

end;

/

 

創建表lock_more 存放 腳本chk_lock.sql 查詢出的結果

SYS @ prod >create table lock_more (locker_sid number,locked_objno number,locked_obj varchar(10),lock_mode varchar(20));

 

Table created.

 

父表插入數據,數據庫中 鎖的情況

SYS @ prod >insert into father values(50,'beijing','china');

 

1 row created.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Row-S (SS)

       154        52515 CHILDEN    Exclusive

       154        52514 FATHER     Row-X (SX)

   154        52514 FATHER     Row-S (SS)

 

結論:INSERT操作會同時鎖定 父表、子表

 

子表插入數據,觀察該對象是否被鎖

SYS @ prod >insert into childen values(1111,'test','test',8888,'28-SEP-81',8,0,50);

 

1 row created.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-S (SS)

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Exclusive

       154        52514 FATHER     Row-S (SS)

       154        52514 FATHER     Row-X (SX)

 

結論:子表插入數據,會同時鎖定 父表、子表

 

 

父表更新數據,觀察該對象 是否被鎖

[oracle@cuug ~]$ vi ct_lock.sql

declare

begin

for i in 4..10000 loop

update father set deptno=deptno*1 ;

end loop;

end;

 /

 

SYS @ prod >@ct_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Row-X (SX)

       154        52514 FATHER     Exclusive

 

結論:對父表做Update操作,只會鎖定父表不會鎖定子表

 

子表更新數據,觀察該對象 是否被鎖

[oracle@cuug ~]$ vi ct_lock.sql

declare

begin

for i in 4..10000 loop

update childen set deptno=deptno*1 ;

end loop;

end;

 /

 

SYS @ prod >@ct_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Row-S (SS)

       154        52514 FATHER     Row-X (SX)

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-S (SS)

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Exclusive

 

結論:在子表執行 update操作,會同時鎖定 父表、子表

 

 

 

 

 

父表刪除數據,觀察該對象 是否被鎖

SYS @ prod >delete from father where deptno=50;

 

1 row deleted.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Row-X (SX)

       154        52514 FATHER     Exclusive

 

結論:在父表執行Delete操作不提交,只會鎖定父表不會鎖定子表

 

 

 

子表刪除數據,觀察對象是否被鎖

SYS @ prod >delete from childen where deptno=50;

 

1 row deleted.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-S (SS)

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Exclusive

       154        52514 FATHER     Row-S (SS)

       154        52514 FATHER     Row-X (SX)

 

結論:在子表執行delete操作不提交,會同時鎖定 父表、子表

 

子表的外鍵字段添加索引

SYS @ prod >create index ind_deptno on childen(deptno);

 

Index created.

 

SYS @ prod >analyze table childen compute statistics;

 

Table analyzed.

 

http://www.itpub.net/forum.php?mod=viewthread&tid=1804873&page=1#pid21588601

 

http://www.itpub.net/forum.php?mod=viewthread&tid=1804873

 

http://www.itpub.net/forum.php?mod=viewthread&tid=1850815&page=2#pid22202575

 

http://www.itpub.net/forum.php?mod=viewthread&tid=1445975

 

 

 

 

 

 

 

父表插入數據,觀察該對象 是否被鎖

SYS @ prod >insert into father values(50,'beijing','china');

 

1 row created.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Row-X (SX)

       154        52514 FATHER     Row-S (SS)

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Row-S (SS)

   154        52515 CHILDEN    Exclusive

 

結論:INSERT操作會同時鎖定 父表、子表

 

子表插入數據,觀察該對象是否被鎖

SYS @ prod >insert into childen values(1111,'test','test',8888,'28-SEP-81',8,0,50);

 

1 row created.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-S (SS)

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Exclusive

       154        52514 FATHER     Row-S (SS)

       154        52514 FATHER     Row-X (SX)

 

結論:子表插入數據,會同時鎖定 父表、子表

 

 

父表更新數據,觀察該對象 是否被鎖

[oracle@cuug ~]$ vi ct_lock.sql

declare

begin

for i in 4..10000 loop

update father set deptno=deptno*1 ;

end loop;

end;

 /

.

SYS @ prod >@ct_lock.sql;

 

PL/SQL procedure successfully completed.

 

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Row-X (SX)

       154        52514 FATHER     Row-X (SX)

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Exclusive

 

結論:Update操作不提交 ,會同時鎖定父表、子表

 

 

子表更新數據,觀察該對象 是否被鎖

SYS @ prod >update childen set deptno=deptno*1 ;

 

14 rows updated.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-S (SS)

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Exclusive

       154        52514 FATHER     Row-S (SS)

       154        52514 FATHER     Row-X (SX)

 

結論:在子表執行 update操作,會同時鎖定 父表、子表

 

父表刪除數據,觀察該對象 是否被鎖

SYS @ prod >delete from father where deptno=50;

 

1 row deleted.

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Row-S (SS)

       154        52515 CHILDEN    Exclusive

       154        52514 FATHER     Row-X (SX)

       154        52514 FATHER     Row-S (SS)

 

結論:父表刪除數據 會同時鎖定 父表、子表

 

 

子表刪除數據,觀察對象是否被鎖

SYS @ prod >delete from childen where deptno=10;

 

3 rows deleted.

 

 

SYS @ prod >@chk_lock.sql;

 

PL/SQL procedure successfully completed.

 

 

SYS @ prod >select * from lock_more;

 

LOCKER_SID LOCKED_OBJNO LOCKED_OBJ LOCK_MODE

---------- ------------ ---------- --------------------

       154        52514 FATHER     Exclusive

       154        52515 CHILDEN    Row-S (SS)

       154        52514 FATHER     Row-S (SS)

       154        52514 FATHER     Row-X (SX)

       154        52515 CHILDEN    Row-X (SX)

       154        52515 CHILDEN    Exclusive

 

結論:子表刪除數據同時 鎖定 主表、子表

 

 

結論:

 

子表外鍵未創建索引

 

INSERT

UPDATE

DELETE

父表

鎖父表、子表

鎖父表

鎖父表、鎖子表

子表

鎖父表、子表

鎖父表、子表

鎖父表、子表

 

 

子表外鍵創建索引

 

INSERT

UPDATE

DELETE

父表

鎖父表、子表

鎖父表、子表

鎖父表、子表

子表

鎖父表、子表

鎖父表、子表

鎖父表、子表

 

 

 

 

 

外鍵上無索引

         如果外鍵(foreign key)上沒有定義索引,當父表(parent table)中的數據行被更新或刪除時,Oracle 采用的鎖機制(locking mechanism)如 圖 21-8 所示。而向父表中插入數據時無需對子表(child table)加鎖。

 

 

如果外鍵上沒有定義索引,對父表的主鍵執行 DML 操作時必須獲得子表上的共享行排他表級鎖(share row exclusive table lock)(也稱為 share-subexclusive table lock,SSX)。此鎖能夠阻止其他事務對子表執行 DML 操作。SSX 鎖在獲得后立即釋放。如果父表中有多個主鍵值被更新或刪除,對每行執行 DML 操作時都需要對子表進行一次加鎖及解鎖操作。
 

           如果外鍵上定義了索引,則對父表的主鍵執行 DML 操作時只需獲得子表上的行共享表級鎖(row share table lock)(也稱為 subshare table lock,SS)。此鎖不允許其他事務排他地對子表加鎖,但允許對父表及子表執行 DML 操作


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM