外键未加索引和加索引的区别

主要描述外键未加索引和加索引的区别:
 
首先建相关表:
create table dept (dept_id number(2), name varchar2(20));   
alter table dept add (constraint pk_dept primary key (dept_id)); 
 
--在外键上没有建索引的子表
CREATE TABLE emp
   (emp_id number(10),
    name varchar2(20) ,
    dept_id number(2) CONSTRAINT fk_emp
                      references dept(dept_id)
                      ON DELETE CASCADE
   );
alter table emp add (constraint pk_emp primary key (emp_id));  
 
insert into dept values (10,'ACCOUNTING'); 
insert into dept values (11,'SALES'); 
insert into dept values (12,'RESEARCH'); 
insert into dept values (14,'TT');  
 
insert into emp values (2001,'Jason',10); 
insert into emp values (2002,'Mike',11); 
insert into emp values (2003,'Green',12); 
insert into emp values (2004,'Grey',10); 
 
外键未加索引情况,实验如下:
实验1、
Session1:对子表进行插入操作:
insert into emp values(2005,'dai',14);
 
session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row share            DEPT                    11         12        503
DAIMIN            142 Row Exclusive        EMP                     11         12        503
 
SQL> @c:\showalllock;
       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row share                     0          6          0
       142 TX       720908        503 Exclusive                     0          6          0
       142 TM        55612          0 Row Exclusive                 0          6          0
分析:对子表进行插入操作时,此时尽管只是对子表操作,但是需要验证被插入的记录中的外键值是否在父表中是否存在,不存在,则会报错;存在的话,则允许插入。此时需要对父表加RS锁,锁住外键值所对应父表被引用键值的行;除了对父表加RS锁之外,对子表还要加RX锁和TX锁。
 
实验2、
Session2:对子表EMP进行更新操作,并且所更新的行在子表中实际不存在或者存在:
update emp  set name=name  where dept_id=15;
或者update emp  set name=name  where dept_id=11;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME          SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        EMP                     14         28        499
 
SQL> @c:\showalllock;
      SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TX       917532        499 Exclusive                     0         87          0
       142 TM        55612          0 Row Exclusive                0         87          0
分析:仅对子表中除外键以外的值进行更新,此时不需要牵涉到父表,所以此时的更新操作不需要对父表加任何的锁,只需要对子表加RX锁和TX锁。
 
实验3、
Session3:对子表进行删除操作,并且由删除条件查询出来的记录为空或者不为空时:
delete from emp where 1=0;
或者 delete from emp ;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row share            DEPT                    17         28        502
DAIMIN            142 Row Exclusive        EMP                     17         28        502
 
SQL> @c:\showalllock;
   SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row share                     0          6          0—DEPT表上的RS
       142 TX      1114140        502 Exclusive                      0          6          0 --EMP表上的TX
       142 TM        55612          0 Row Exclusive                 0          6          0 –EMP表上的RX
注:BLOCK=1 :表示锁被阻塞;BLOCK=0,表示未阻塞。
分析:对子表进行删除操作,也需要对父表加RS锁,猜想是因为需要验证被删除的这些记录中的外键值是否在父表还存在,所以需要在父表中加RS锁。然后对子表本身需要加RX锁和TX锁。
 
实验4、
Session4:更新子表的外键列:
update emp set dept_id= 12 where dept_id=11;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row share            DEPT                    12         17        661
DAIMIN            142 Row Exclusive        EMP                     12         17        661
 
SQL> @c:\showalllock;
    SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row share                     0          6          0
       142 TX       786449         661 Exclusive                     0          6          0
       142 TM        55612          0 Row Exclusive                 0          6          0
分析:和实验2比较,都是对子表进行更新操作,但是该实验是对外键值进行的更新,牵涉到父表,所以需要对父表DEPT加RS锁,子表EMP本身需要加RX锁和TX锁。
 
实验5、
Session5:对父表进行插入操作:
insert into dept values(15,'daimin');
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN   XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        DEPT                   13         36        671
DAIMIN            142 Row share            EMP                     13         36        671
 
SQL> @c:\showalllock;
      SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row Exclusive                 0          6          0
       142 TX       852004         671 Exclusive                     0          3          0
       142 TM        55612          0 Row share                     0          6          0
分析:对父表进行插入操作,此时需要对父表DEPT加RX锁和TX锁,同时需要对子表EMP加RS锁。
 
实验6、
Session4:对父表DEPT进行更新操作,并且所更新的行在父表中实际不存在或者不存在:
update dept set name=name where dept_id=16;
或者 update dept set name=name where dept_id=12;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        DEPT                    15         18        668
 
SQL> @c:\showalllock;
       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TX       983058        668 Exclusive                     0          6          0
       142 TM        55606          0 Row Exclusive                 0          6          0
分析:仅对父表中的记录进行更新,此时不需要牵涉到子表,所以此时的更新操作不需要对子表加任何的锁,只需要对父表加RX锁和TX锁。
 
 
实验7、
Session7: 对父表DEPT进行删除操作,并且所更新的行在父表中实际不存在或者实际存在:
delete from dept where 1=0;
或者 delete from dept where dept_id=12;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        DEPT                    15         28        671
DAIMIN            142 Row Exclusive        EMP                     15         28        671
 
SQL> @c:\showalllock;
     SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row Exclusive                 0          6          0
       142 TX       983068        671 Exclusive                     0          6          0
       142 TM        55612          0 Row Exclusive                 0          6          0
分析:对父表DEPT与子表EMP都加了RS锁,并且由于是对DEPT父表进行删除行记录,所以为父表加了TX锁。有点疑问:我在创建子表时使用了ON DELETE CASCADE语句,为什么我在删除父表的记录时没有造成子表的相应记录删除呢?猜想应该在子表EMP上也应该有TX锁。
 
外键加索引情况,实验如下:
给表EMP的外键添加索引如下:
-- Create/Recreate indexes on the Foreign Key
create index EMP_DEPT_ID on EMP (DEPT_ID);
 
实验1、
Session1:对子表进行插入操作:
insert into emp values(2005,'dai',14);
 
session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row share            DEPT                    19         47        673
DAIMIN            142 Row Exclusive        EMP                    19         47        673
 
SQL> @c:\showalllock;
       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row share                     0          6          0
       142 TX      1245231        673 Exclusive                     0          6          0
       142 TM        55612          0 Row Exclusive                 0          6          0
分析:与外键没有加索引的情况中的实验1所加的锁一样,没有区别。
 
实验2、
Session2:对子表EMP进行更新操作,并且所更新的行在子表中实际不存在或者存在:
update emp  set name=name  where dept_id=15;
或者update emp  set name=name  where dept_id=11;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        EMP                     13         13        676
 
SQL> @c:\showalllock;
       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TX       851981        676 Exclusive                     0          6          0
       142 TM        55612          0 Row Exclusive                 0          6          0
分析:与外键没有加索引的情况中的实验2所加的锁一样,没有区别。
 
 
实验3、
Session3:对子表进行删除操作,并且由删除条件查询出来的记录为空或者不为空时:
delete from emp where 1=0;
或者 delete from emp ;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row share            DEPT                    17         28        502
DAIMIN            142 Row Exclusive        EMP                     17         28        502
 
SQL> @c:\showalllock;
    SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row share                     0          6          0—DEPT表上的RS
       142 TX      1114140        502 Exclusive                      0          6          0 --EMP表上的TX
       142 TM        55612          0 Row Exclusive                 0         6          0 –EMP表上的RX
注:BLOCK=1 :表示锁被阻塞;BLOCK=0,表示未阻塞。
分析:与外键没有加索引的情况中的实验3所加的锁一样,没有区别。
 
实验4、
Session4:更新子表的外键列:
update emp set dept_id= 12 where dept_id=11;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row share            DEPT                    12         17        661
DAIMIN            142 Row Exclusive        EMP                     12         17        661
 
SQL> @c:\showalllock;
    SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row share                     0          6          0
       142 TX       786449         661 Exclusive                     0          6          0
       142 TM        55612          0 Row Exclusive                 0          6          0
分析:与外键没有加索引的情况中的实验4所加的锁一样,没有区别。
 
实验5、
Session5:对父表进行插入操作:
insert into dept values(15,'daimin');
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        DEPT                   13         36        671
DAIMIN            142 Row share            EMP                     13         36        671
 
SQL> @c:\showalllock;
      SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row Exclusive                 0          6          0
       142 TX       852004         671 Exclusive                     0          3          0
       142 TM        55612          0 Row share                     0          6          0
分析:与外键没有加索引的情况中的实验5所加的锁一样,没有区别。
 
实验6、
Session4:对父表DEPT进行更新操作,并且所更新的行在父表中实际不存在或者不存在:
update dept set name=name where dept_id=16;
或者 update dept set name=name where dept_id=12;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        DEPT                    15         18        668
 
SQL> @c:\showalllock;
       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TX       983058        668 Exclusive                     0          6          0
       142 TM        55606          0 Row Exclusive                 0          6          0
分析:与外键没有加索引的情况中的实验6所加的锁一样,没有区别。
 
实验7
Session7: 对父表DEPT进行删除操作,并且所更新的行在父表中实际不存在:
delete from dept where 1=0;
 
Session0:此时加锁的信息都是如下:
 
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        DEPT                    13         38        676
DAIMIN            142 Row share            EMP                     13         38        676
 
SQL> @c:\showalllock;
     SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row Exclusive                 0          5          0
       142 TX       852006        676 Exclusive                     0          5          0
       142 TM        55612          0 Row share                    0          5          0
分析:猜测可能是由于在父表中根本没有查找到记录,所以就在子表中不需要对子表EMP行进行删除,所以对子表EMP加的是RS锁。这里和外键没有加索引的情况中的实验7所加的锁一样有锁不一样,在子表中所加的锁是RS锁,而不是RX锁。
 
实验8、
Session7: 对父表DEPT进行删除操作,并且所更新的行在父表中实际存在:
 delete from dept where dept_id=12;
 
Session0:此时加锁的信息都是如下:
SQL> @c:\showlock;
O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN
---------- ---------- -------------------- --------------- ---------- ---------- ----------
DAIMIN            142 Row Exclusive        DEPT                    15         28        671
DAIMIN            142 Row Exclusive        EMP                     15         28        671
 
SQL> @c:\showalllock;
     SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK
---------- ---- ---------- ---------- -------------------- ---------- ---------- ----------
       142 TM        55606          0 Row Exclusive                 0          6          0
       142 TX       983068        671 Exclusive                     0          6          0
       142 TM        55612          0 Row Exclusive                 0          6          0
分析:与外键没有加索引的情况中的实验7所加的锁一样,没有区别。

posted on 2008-06-18 15:19 球球 阅读(598) 评论(0)  编辑  收藏 所属分类: Oracle


只有注册用户登录后才能发表评论。


网站导航:
 
<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

导航

统计

留言簿(1)

文章分类(19)

文章档案(19)

积分与排名

最新随笔

最新评论