如何找出 Oracle 死锁的原因

Posted

技术标签:

【中文标题】如何找出 Oracle 死锁的原因【英文标题】:How to find out the cause of an Oracle deadlock 【发布时间】:2013-12-09 16:00:15 【问题描述】:

在使用多个用户测试我的应用程序时,我遇到了 ORA-00060 死锁错误。我不确定如何确定这个错误的原因,所以如果有人可以帮助我,将不胜感激。

我查看了为此事件生成的跟踪文件,它告诉我是哪个查询导致了这个:

UPDATE TABLE_A SET CK=CK+1 WHERE A_ID=(
    SELECT A_ID FROM TABLE_B WHERE SOME_COLUMN=:SOMECOLUMN
)

它也产生了这个:

[Transaction Deadlock]

The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or from issuing incorrect ad-hoc SQL. The following
information may aid in determining the deadlock:

Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TM-0002a675-00000000        51     200    SX   SSX       52      22    SX   SSX
TM-0002a675-00000000        52      22    SX   SSX       51     200    SX   SSX

session 200: DID 0001-0033-0000014A session 22: DID 0001-0034-0000005A 
session 22: DID 0001-0034-0000005A  session 200: DID 0001-0033-0000014A 

Rows waited on:
  Session 200: obj - rowid = 0002A6B1 - AAAqaxAAUAAAAFTAAA
  (dictionary objn - 173745, file - 20, block - 339, slot - 0)
  Session 22: obj - rowid = 0002A6B1 - AAAqaxAAUAAAAFTAAA
  (dictionary objn - 173745, file - 20, block - 339, slot - 0)

如何使用以上信息找出问题的原因? TABLE_A 或 TABLE_B 上没有任何未索引的外键(我认为这通常是导致此类错误的原因)。

当我运行这个查询时:

SELECT OWNER, OBJECT_NAME, OBJECT_TYPE 
FROM DBA_OBJECTS 
WHERE OBJECT_ID = 173745;

我得到了一个完全不同的表上的主键名称!这可能是为什么会发生死锁的线索吗?

【问题讨论】:

我认为您的问题是 Stack Overflow 的主题,但只是想确保您了解 Database Administrators。可能有人在该网站上了解这些类型的问题。 【参考方案1】:

因为所涉及的入队是“TM”入队,并且因为持有锁的模式是“SX”,而等待锁的模式是“SSX”,所以我可以绝对肯定地告诉你,这是由于外键关系,其中引用表(子表)列未编入索引。如果你寻找未索引的外键并添加索引,这个问题应该会消失。

希望对您有所帮助....

附:我的演示文稿“理解和解释死锁,或者,如何处理 ORA-00060”,可在 OakTable 站点 http://www.oaktable.net 下载。查看“提供的文件”部分。

【讨论】:

是的,这就是问题的原因。我使用 Tom Kyte 的查询 (asktom.oracle.com/pls/asktom/…) 找到所有未索引的外键并修复它们,从而解决了问题。我仍然不太明白为什么未索引的外键会导致这种情况发生 - 我希望您的演示文稿可以对此有所了解!感谢您的帮助。 抱歉,我的演讲没有详细说明为什么未索引的外键会导致锁定问题。我的演讲有点务实地解决了这个问题。如果您遇到 ORA-00060,让我们查看跟踪文件,具体而言,死锁图、死锁涉及的 SQL 以及死锁涉及的行,并尝试明确确定死锁的根本原因。 如果您有兴趣了解为什么锁定的工作方式以及未索引外键导致锁定问题的原因,您最好查看Oracle 文档。具体见docs.oracle.com/cd/E16655_01/server.121/e17633/… 就个人而言,我总是索引 FK。如果您查看此处:docs.oracle.com/cd/E16655_01/server.121/e17633/…,您会看到 Oracle 强烈 建议这样做,但讨论了一种可能允许您不创建索引的特定情况。总的来说,我认为这是一个好主意,除非你真的想将你的系统调优到第 n 级,并且你真的很关心可伸缩性问题。通常,额外索引的好处足以弥补任何开销或可伸缩性损失。 是的,没错。在那种情况下,如果没有检测到死锁,这两个会话将永远卡住。

以上是关于如何找出 Oracle 死锁的原因的主要内容,如果未能解决你的问题,请参考以下文章

问题从 oracle 跟踪文件中查找死锁错误的原因

Oracle数据库死锁问题,高分悬赏答案

500分悬赏oracle死锁问题解决,决不食言

查找Java应用程序死锁原因的工具[关闭]

Oracle死锁

如何杀死oracle死锁进程