ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 外键缺少索引引发的死锁

外键缺少索引引发的死锁

Linux操作系统 作者:mengbing1990 时间:2016-12-19 13:30:34 0 删除 编辑

客户的10.2.0.4 RAC for AIX环境频繁出现ORA-60死锁问题,导致应用程序无法顺利执行。

 

 

经过一系列的诊断,发现最终问题是由于外键上没有建立索引所致,由于程序在主子表上删除数据,缺少索引导致行级锁升级为表级锁,最终导致大量的锁等待和死锁。

下面通过一个例子简单模拟一下问题:

SQL> create table t_p (id number primary key, name varchar2(30));

Table created.

SQL> create table t_f (fid number, f_name varchar2(30), foreign key (fid) references t_p);

Table created.

SQL> insert into t_p values (1, 'a');

1 row created.

SQL> insert into t_f values (1, 'a');

1 row created.

SQL> insert into t_p values (2, 'b');

1 row created.

SQL> insert into t_f values (2, 'c');

1 row created.

SQL> commit;

Commit complete.

SQL> delete t_f where fid = 2;

1 row deleted.

这时在会话2同样对子表进行删除:

SQL2> delete t_f where fid = 1;

1 row deleted.

回到会话1执行主表的删除:

SQL> delete t_p where id = 2;

会话被锁,回到会话2执行主表的删除:

SQL2> delete t_p where id = 1;

会话同样被锁,这时会话1的语句被回滚,出现ORA-60死锁错误:

delete t_p where id = 2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource


SQL> rollback;

Rollback complete.

将会话1操作回滚,会话2同样回滚并建立外键列上的索引:


1 row deleted.

SQL2> rollback;

Rollback complete.

SQL2> create index ind_t_f_fid on t_f(fid);

Index created.

重复上面的步骤会话1删除子表记录:

SQL> delete t_f where fid = 2;

1 row deleted.

会话2删除子表记录:

SQL2> delete t_f where fid = 1;

1 row deleted.

会话1删除主表记录:

SQL> delete t_p where id = 2;

1 row deleted.

会话2删除主表记录:

SQL> delete t_p where id = 1;

1 row deleted.

所有的删除操作都可以成功执行,关于两种情况下锁信息的不同这里就不深入分析了,重点就是在外键列上建立索引。

虽然有一些文章提到过,如果满足某些情况,可以不在外键列上建立的索引,但是我的观点一向是,既然创建了外键,就不要在乎再多一个索引,因为一个索引所增加的代价,与缺失这个索引所带来的问题相比,是微不足道的。

 

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29551564/viewspace-2130928/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
v❤550166897

注册时间:2014-03-19

  • 博文量
    88
  • 访问量
    195221