外键缺少索引引发的死锁

from:http://yangtingkun.net/?p=264

客户的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.

所有的删除操作都可以成功执行,关于两种情况下锁信息的不同这里就不深入分析了,重点就是在外键列上建立索引。
虽然有一些文章提到过,如果满足某些情况,可以不在外键列上建立的索引,但是我的观点一向是,既然创建了外键,就不要在乎再多一个索引,因为一个索引所增加的代价,与缺失这个索引所带来的问题相比,是微不足道的。

在面试过程中,区分MySQL的InnoDB、MYISAM和Memory存储引擎是常见的技术问题。对于求职者来说,深入理解这些存储引擎的特性至关重要。《MySQL面试宝典:全面解析常见引擎与实战应用》提供了对这些问题的全面解析,帮助求职者更好地准备面试。 参考资源链接:[MySQL面试宝典:全面解析常见引擎与实战应用](https://wenku.youkuaiyun.com/doc/4e2npfvpdx?spm=1055.2569.3001.10343) InnoDB存储引擎支持事务处理,拥有行级定和约束机制,这使其非常适合处理复杂的事务要求。它的行级可以最大限度地提高并发处理能力,同时MVCC支持能够减少死锁的风险。在索引支持方面,InnoDB使用B+树结构,支持全文索引。 相比之下,MYISAM存储引擎不支持事务,仅有定机制,适用于读操作密集型的应用,如数据仓库或日志系统。MYISAM在处理大量并发读取时具有优势,但其机制和缺少事务支持使得它不适合需要复杂事务处理的应用场景。MYISAM使用B+树结构存储索引,但不支持全文索引,这是它的一个重要限制。 Memory存储引擎则使用内存来存储数据,从而实现快速访问,特别适合用于临时或缓存用途。由于数据存储在内存中,所以当服务器重启时数据会丢失,这限制了其使用场景。在索引方面,Memory存储引擎使用哈希索引,可以支持更快的查找速度。它同样不支持事务和。 在选择存储引擎时,应考虑应用的具体需求,如是否需要事务支持、索引类型、并发控制的需求,以及是否能够容忍数据丢失。例如,对于需要高并发读写支持的应用,可以选择InnoDB。对于只读或读多写少的应用,MYISAM可能是更好的选择。而对于需要快速数据访问和临时存储的场景,Memory存储引擎可能更加适用。 总体而言,《MySQL面试宝典:全面解析常见引擎与实战应用》不仅提供了对这些常见存储引擎深入的讲解,还包括了它们在实际应用中的对比分析,使得求职者在面试中能够自信地应对任何关于MySQL存储引擎的问题。 参考资源链接:[MySQL面试宝典:全面解析常见引擎与实战应用](https://wenku.youkuaiyun.com/doc/4e2npfvpdx?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值