日期:2014-05-16  浏览次数:20446 次

oracle外键引起的死锁

?

今天系统测试的时候,发现经常发送oracle的死锁,然后我打开pl/sql看是两张表;再细看它们是主从表关系。

具体的表信息如下:

?

-- 主表
create table LABLEINFOS_TABLE
(
  LABLE_ID   VARCHAR2(38) not null,
  LABLE_NAME VARCHAR2(200) not null,
  CREATOR    VARCHAR2(38) not null,
  CREATETIME DATE not null,
  EDITOR     VARCHAR2(38),
  EDITTIME   DATE,
  constraint PK_LABLEINFOS_TABLE primary key (LABLE_ID)
);

?

?

-- 从表
create table SCHEME_LABLE_RERATION_TABLE
(
  ID           VARCHAR2(38) not null,
  LABLE_ID     VARCHAR2(38),
  MA_SD_SEQ_ID VARCHAR2(38) not null,
  CREATOR      VARCHAR2(38),
  CREATTIME    DATE,
  constraint PK_SCHEME_LABLE_RERATION_TABLE primary key (ID)
);
alter table SCHEME_LABLE_RERATION_TABLE
  add constraint FK_SCHEME_L_REFERENCE_LABLEINF foreign key (LABLE_ID)
  references LABLEINFOS_TABLE (LABLE_ID);
?

?

有两存储过程需要对这两张表进行DML操作。

?

我记得tom说过:”不加索引的外键是死锁的头号原因“。

?

大概的原因知道了之后,我先把外键给删除了进行测试,果然不会发送死锁了。

?

现在把Tomas Keyte的书《Oracle 9i & 10g编程艺术》(强烈推荐)上的内容记录如下:

?

?

据Tomas?的经验,导致死锁的头号原因是外键未加索引(第二号原因是表上的位图索引遭到并发更新)。在以下两种情况下,Oracle在修改父表后会对子表加一个全表锁:

?

  • 如果更新了父表的主键(倘若遵循关系数据库的原则,即主键应当是不可变的,这种情况就很少见。)由于外键上没有索引,所以子表会被锁住。
  • 如果删除了父表中的一行,整个子表也会被锁住(由于外键上没有索引,比如:如果EMP表有DEPT的一个外键,而且在EMP表的DEPTNO列上没有任何索引,那么更新DEPT时整个EMP表都会被锁定)。
除了全表锁外,在以下情况下,未加索引的外键也可能带来问题:
  • 如果有on delete cascade,而且没有对子表加索引:例如,emp是dept的子表,delete deptno=10应该cascade(级联)至emp。如果emp中的deptno没有索引,那么删除dept表中的每一行时都会对emp做一次全表扫描。这个全表扫描可能是不必要的,而且如果从父表删除多行,父表中每删除一行就要扫描仪一次子表。
  • 从父表查询子表:在此考虑emp/dept例子。利用deptno查询emp表是相当常见的。如果频繁地运行以下查询,你就会发现没有索引会使查询速度变慢:select * from dept, emp where emp.deptno=dept.deptno and dept.deptno=:x;

-EOF-

?