更新和删除表中的不同行时是否可能出现死锁?

时间:2012-07-27 16:03:27

标签: oracle

在Oracle 10+版本中,即使它们同时在同一个表的不同行上运行,也能在同一个表上更新和删除导致死锁吗?

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

没有父/子关系

我相信它不会造成僵局,但我的申请中遇到了一个问题。

添加oracle trace:

以下死锁不是ORACLE错误。由于应用程序设计中的用户错误或发出不正确的临时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

2 个答案:

答案 0 :(得分:10)

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

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

再次发布上述请求的信息,我相信我们可以确定导致死锁的根本原因。

于2012年7月30日添加**

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

死锁图显示锁定的模式是'X'(不包括),锁等待的模式是'X',这告诉我这是简单的行级锁定。

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

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

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

其他一些信息:

  • 排队类型是TX(参见死锁图),因此,由于未编入索引的外键,这肯定是锁定。如果由于未编制索引的FK而锁定,则入队类型将是TM,而不是TX。 (至少还有一个涉及TM队列的案例,并且它不是未编入索引的FK。因此,不要认为TM队列总是意味着未编入索引的FK。)

  • 等待锁的模式是'X'(不包括),因此这是行级锁定。如果等待的模式是'S'(共享),则是行级锁定。相反,它可能是ITL短缺或PK或英国执法。

希望有所帮助!

答案 1 :(得分:8)

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

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数据库最大化与依赖外键相关的父键的并发控制。锁定行为取决于是否对外键列进行索引。如果未对外键进行索引,则子表可能会更频繁地被锁定,将发生死锁,并且会降低并发性。因此,外键几乎总是要编入索引。唯一的例外是永远不会更新或删除匹配的唯一键或主键。

锁定和未编制索引的外键

如果满足以下两个条件,则数据库将在子表上获取完整的表锁:

子表的外键列上没有索引。

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

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