在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
答案 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。