关于子表外健索引的问题

[复制链接]
查看11 | 回复5 | 2009-7-22 09:30:00 | 显示全部楼层 |阅读模式
看TOM的书,,,上面有提到这个问题,说是建立外健索引可以避免子表被锁定,就是在DML的时候,可以防止等待,实验也作过了,可以的
现在就是不大明白其中的原理,书上说没有外键索引,锁住的是整个表,有了索引,锁住的是加了索引的哪个列,因此在多个会话操作的时候,可以避免锁
这个地方不理解,,
回复

使用道具 举报

千问 | 2009-7-22 09:30:00 | 显示全部楼层
你先试验一下,什么情况下会锁主外键的表?
回复

使用道具 举报

千问 | 2009-7-22 09:30:00 | 显示全部楼层
SQL> CREATE TABLE T_P (ID NUMBER, NAME VARCHAR2(30));
表已创建。
SQL> ALTER TABLE T_P ADD PRIMARY KEY (ID);
表已更改。
SQL> CREATE TABLE T_C (ID NUMBER, FID NUMBER, NAME VARCHAR2(30));
表已创建。
SQL> ALTER TABLE T_C ADD CONSTRAINT FK_T_C
2 FOREIGN KEY (FID)
3 REFERENCES T_P (ID);
表已更改。
SQL> INSERT INTO T_P SELECT ROWNUM, TABLE_NAME FROM ALL_TABLES;
已创建884行。
SQL> INSERT INTO T_C SELECT ROWNUM, MOD(ROWNUM, 884) + 1, OBJECT_NAME
2 FROM ALL_OBJECTS;
已创建30339行。
SQL> COMMIT;
提交完成。
SQL> CREATE INDEX IND_T_C_FID ON T_C (FID);
索引已创建。
SQL> SELECT * FROM T_P WHERE IDSELECT * FROM T_C WHERE IDSET SQLP 'SQL2> '
  SQL2> DELETE T_C WHERE ID = 2;
  已删除 1 行。
  删除了一条为2的子表级联,其对应的主表记录ID为3,下面尝试在第一个会话新增一条ID为1000的记录,然后删除这条记录:
  SQL> INSERT INTO T_P VALUES (1000, 'A');
  已创建 1 行。
  SQL> DELETE T_P WHERE ID = 1000;
  已删除 1 行。
  SQL> ROLLBACK;
  回退已完成。
  可以看到,并没有发生锁表的情况,这是因为子表外键列上有索引,删除主表的记录时,只会锁定子表参考主表的对应记录。
  会话二回滚:
  SQL2> ROLLBACK;
  回退已完成。
  下面删除外键索引:
  SQL> DROP INDEX IND_T_C_FID;
  索引已删除。
  重复刚才的操作,在另一个会话执行删除操作:
  SQL2> DELETE T_C WHERE ID = 2;
  已删除 1 行。
  在会话一重复插入和删除操作:
  SQL> INSERT INTO T_P VALUES (1000, 'A');
  已创建 1 行。
  SQL> DELETE T_P WHERE ID = 1000;
  这时会话被锁住,因为缺少了外键索引后,主表删除或更新记录会导致子表整个表被锁,而这会导致严重的系统并发问题。
  SQL2> ROLLBACK;
  回退已完成。
  会话2回滚后,会话1的删除操作才可以继续执行:
  已删除 1 行。
回复

使用道具 举报

千问 | 2009-7-22 09:30:00 | 显示全部楼层
就是这个实验
回复

使用道具 举报

千问 | 2009-7-22 09:30:00 | 显示全部楼层
为什么建立索引了,就只会锁定参考主表的对应记录
回复

使用道具 举报

千问 | 2009-7-22 09:30:00 | 显示全部楼层
原帖由 macheraters 于 2009-4-5 12:02 发表
为什么建立索引了,就只会锁定参考主表的对应记录

这是因为ORACLE的并发控制机制。
外键上没有定义索引,对父表的主键执行 DML 操作时必须获得子表上的共享行排他表级锁;如果外键上定义了索引,则对父表的主键执行 DML 操作时只需获得子表上的行共享表级锁。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行