9

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

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

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

添加 oracle 跟踪:

以下死锁不是 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
4

2 回答 2

10

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

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

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

添加于 2012 年 7 月 30 日 **

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

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

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

同时,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 或英国执法。

希望有帮助!

于 2012-07-27T18:45:26.793 回答
9

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

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。

于 2012-07-27T17:52:20.323 回答