【问题标题】:Is a deadlock possible when updating and deleting different rows in a table?更新和删除表中的不同行时是否可能出现死锁?
【发布时间】:2012-08-01 01:32:42
【问题描述】:

在Oracle 10+版本中,对同一张表的更新和删除是否会导致死锁,即使它们同时对同一张表的不同行进行操作?

该表具有由两列组成的主键,并且没有与任何其他表关联/引用的任何 FK。并且与其他表没有父子关系

我相信它不会造成死锁,但我的应用程序遇到了问题。

添加预言机跟踪:

以下死锁不是 ORACLE 错误。这是由于用户在应用程序设计中的错误或发出不正确的 ad-hoc SQL 而导致的死锁。以下信息可能有助于确定死锁:

Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-0007003e-0081d6c3        45     790     X            104      20           X
TX-00080043-0085e6be       104      20     X             45     790           X

session 790: DID 0001-002D-000035F9     session 20: DID 0001-0068-000007F6
session 20: DID 0001-0068-000007F6      session 790: DID 0001-002D-000035F9

Rows waited on:
  Session 790: obj - rowid = 0000F0C8 - AAAPDIAAMAAAEfIAAA
  (dictionary objn - 61640, file - 12, block - 18376, slot - 0)
  Session 20: obj - rowid = 0000F0C8 - AAAPDIAAMAAAEfGAAA
  (dictionary objn - 61640, file - 12, block - 18374, slot - 0)

----- Information for the OTHER waiting sessions ----- Session 20:
  sid: 20 ser: 4225 audsid: 57496371 user: 72/RPT_TABLE
    flags: (0x45) USR/- flags_idl: (0x1) BSY/-/-/-/-/-
    flags2: (0x40009) -/-/INC
  pid: 104 O/S info: user: oracle, term: UNKNOWN, ospid: 20798
    image: oracle@caidb10p-node1
  client details:
    O/S info: user: gtsgen, term: unknown, ospid: 1234
    machine: caiapp08p-node0.nam.nsroot.net program: JDBC Thin Client
    application name: JDBC Thin Client, hash value=2546894660
  current SQL:
  delete from RPT_TABLE.TEMP_TABLE_T1 where TEMP_T1_ID=:1

----- End of information for the OTHER waiting sessions -----

Information for THIS session:

----- Current SQL Statement for this session (sql_id=bsaxpc2bdps9q) ----- UPDATE RPT_TABLE.TEMP_TABLE_T1 temp1 SET temp1.CLIENT_ID = (SELECT MIN(INVMAP.CLIENT_ID) FROM LI_REF.REF_CLIENT_MAP INVMAP WHERE INVMAP.F_CODE = :B2 AND INVMAP.AID = temp1.ID AND temp1.R_ID=:B1 )
----- PL/SQL Stack -----
----- PL/SQL Call Stack -----
  object      line  object
  handle    number  name
45887d750        24  procedure RPT_TABLE.T1_UPDATE_StoredProc  

6399ba188         1  anonymous block

【问题讨论】:

  • 如果所有事务都在更新完全不同的行,那么死锁似乎不太可能发生。如果您面对的是一个,那么我怀疑有些交易确实会更新相同的行
  • 您面临什么问题?除了非常模糊的答案之外,这太模糊了,无法给出任何答案,并告诉您阅读文档。您认为导致您的问题的代码(无论它是什么)也会有所帮助,以及正在发生的确切情况,包括任何错误消息。

标签: oracle


【解决方案1】:

如果您可以使用死锁图更新您的问题,那将是有用的信息。 (当您的应用程序遇到死锁时,Oracle 将引发 ORA-00060,并将跟踪文件写入 user_dump_dest。)如果您查看跟踪文件,您会发现一个名为“死锁图”的部分。如果你能把它贴出来,并且把导致死锁的语句和其他涉及死锁的语句贴出来,那么我们就可以开始得出一些结论了。 (我要求的所有信息都在跟踪文件中。)

正如 Alessandro 所提到的,由于父/子关系的子表上的未索引外键,会话锁定同一个表中的不同行可能会导致死锁。此外,即使该表不属于父/子关系(例如,该表缺少 ITL 条目),更新同一个表的不同行的两个会话也可能出现死锁。

再次发布上面要求的信息,我相信我们可以确定您陷入僵局的根本原因。

添加于 2012 年 7 月 30 日**

添加以下内容,现在已经提供了死锁跟踪文件: 好的,首先,根据跟踪文件内容,这是一个简单的死锁,因为会话在他们试图锁定的行上重叠/冲突。尽管您之前的 cmets 关于死锁位于 不同 行,但我在这里告诉您,这种特殊的死锁是由于 same 行上的行级锁定造成的。

死锁图显示锁的持有模式是“X”(独占),而锁等待的模式是“X”,这告诉我这是简单的行级锁定。

在这种情况下,SID 20 正在执行“从 RPT_TABLE.TEMP_TABLE_T1 中删除,其中 TEMP_T1_ID=:1”并且已经锁定了 rowid AAAPDIAAMAAAEfIAAA。

同时,SID 790 正在执行“RPT_TABLE.T1_UPDATE_StoredProc”,同时已经锁定了 rowid AAAPDIAAMAAAAEfGAAA。

从跟踪文件的“等待的行”部分注意,SID 20 正在等待 SID 790 持有的行,而 SID 790 正在等待 SID 20 持有的行。这是典型的僵局。

一些附加信息:

  • 队列类型是 TX(参见死锁图),因此,这绝对是 不是 由于未索引的外键而导致的锁定。如果它由于未索引的 FK 而被锁定,则入队类型将是 TM,而不是 TX。 (至少还有一种涉及 TM 入队的情况,它不是未索引的 FK。因此,不要假设 TM 入队总是意味着未索引的 FK。)

  • 等待锁的模式是“X”(独占),所以这是行级锁定。如果等待的模式是“S”(共享),那么它不是是行级锁定。相反,这可能是 ITL 短缺或 PK 或英国执法。

希望有帮助!

【讨论】:

  • 感谢您的详细回复。至于 user_dump_dest 位置,我可以从 user_dump_dest 获取一周的跟踪文件吗?
  • 就父/子而言,情况并非如此,不是 FK ......但是是的,正如你所提到的......有 2 个会话更新同一张表的不同行......请在这方面为我提供更多指导……ITL 整体短缺……请求您详细说明这一点……
  • 与其猜测原因,请发布死锁跟踪文件中的信息。至于您是否可以检索一周前的跟踪文件,这取决于您的 user_dump_dest 有多大,清理它的频率等。我建议您尝试执行 'grep -l "ORA-00060" * .trc',在 user_dump_dest 目录中。
  • 也添加了相同的跟踪
【解决方案2】:

我不知道您的应用程序中是否包含外键,但它可能是您的锁的来源。如果是这样,请查看以下链接:

http://docs.oracle.com/cd/E11882_01/server.112/e16508/consist.htm#BABCAHDJ

http://docs.oracle.com/cd/E11882_01/server.112/e16508/datainte.htm#CNCPT1657

Oracle 数据库最大限度地提高了父键相对于依赖外键的并发控制。锁定行为取决于外键列是否被索引。如果没有索引外键,那么子表可能会更频繁地被锁定,出现死锁,并发性会降低。出于这个原因,外键几乎总是应该被索引。唯一的例外是匹配的唯一键或主键从未更新或删除。

锁和未索引的外键

当以下两个条件都为真时,数据库获取子表的全表锁:

子表的外键列上不存在索引。

会话修改父表中的主键(例如,删除行或修改主键属性)或将行合并到父表中。对父表的插入不会获取子表上的表锁。

如果这不是您的情况,请尝试提供更多相关信息。告诉我们会话持有/请求的锁类型,并查看系统表 V$LOCK、V$LOCKED_OBJECT、DBA_DDL_LOCKS、DBA_DML_LOCKS 或 V$SESSION_WAIT。

【讨论】:

  • 谢谢,这是我的情况。更糟糕的是——父表甚至不包含任何行。真的——从空表中删除会在引用表上产生 TM 锁。添加索引很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多