oracle 锁和闩_笔记6:死锁问题
死锁
如果有两个会话,每个会话都持有另一个会话想要的资源,此时就会出现死锁(deadlock)。例如,如果数据库中有两个表A和B,每个表中都只有一行,就可以很容易地展示什么是死锁。要做的只是打开两个会话。在会话A中更新表A,并在会话B中更新表B。现在,如果想在会话B中更新表A,就会阻塞。会话A已经锁定了这一行。这不是死锁,只是阻塞而已。
如果再回到会话A,试图更新表B,这就会导致一个死锁。要在这两个会话中选择一个作为“牺牲品”,让它的语句回滚。例如,会话B中对表A的更新可能回滚。
想要更新表B的会话A还阻塞着,Oracle不会回滚整个事务。只会回滚与死锁有关的某条语句。会话B仍然锁定着表B中的行,而会话A还在耐心地等待这一行可用。收到死锁消息后,会话B必须决定将表B上未执行的工作提交还是回滚,或者继续走另一条路,以后再提交。一旦这个会话执行提交或回滚,另一个阻塞的会话就会继续,好像什么也没有发生过一样。
Oracle认为死锁很少见,而且由于如此少见,所以每次出现死锁时它都会在服务器上创建一个跟踪文件。
显然,Oracle认为这些应用死锁是应用自己导致的错误,而且在大多数情况下,Oracle的这种看法都是正确的。不同于许多其他的RDBMS,Oracle中极少出现死锁,甚至可以认为几乎不存在。通常情况下,必须人为地提供条件才会产生死锁。
导致死锁的头号原因是外键未加索引(第二号原因是表上的位图索引遭到并发更新)。在以下3种情况下,Oracle在修改父表后会对子表加一个全表锁。
.如果更新了父表的主键,由于外键上没有索引,所以子表会被锁住
.如果删除了父表中的一行,整个子表也会被锁住(由于外键上没有索引)
.如果合并到父表,整个子表也会锁定(没有外键上的索引)。注意这一点只适用于9i和10g,在11g Release 1及以上版本中不再成立。
在9i及以上版本中,这些全表锁都是短期的,这意味着它们仅在DML操作期间存在,而不是在整个事务期间都存在。即使如此,这些全表锁还是可能导致很严重的锁定问题。
更新主键值也会发生这种阻塞。因为在关系数据库中,更新主键是一个很大的禁忌,所以更新在这方面一般没有什么问题。
除了全表锁外,在以下情况下,未加索引的外键也可能带来问题。
.如果有ON DELETE CASCADE,而且没有对子表加索引,例如,EMP是DEPT的子表,DELETE DEPTNO=10应该CASCADE(级联)至EMP。如果EMP中的DEPTNO没有索引,那么删除DEPT表中的每一行时都会对EMP做一个全表扫描。这个全表扫描可能是不必要的,而且如果从父表删除多行,父表中每删除一行就要扫描一次
.从父表查询子表
那么,什么时候不需要对外键加索引呢?答案是,一般来说,当满足以下条件时不需要加索引。
.没有从父表删除行
.没有更新父表的唯一键/主键值
.没有从父表联结子表
如果满足上述全部3个条件,那你完全可以跳过索引,不需要对外键加索引。
如果满足以上的某个条件,就要当心加索引的后果。这是一种少有的情况,即Oracle“过分地锁定了”数据。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5197.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
