Oracle死锁图

时间:2019-03-22 21:00:22

标签: oracle concurrency parallel-processing

我们的一个合并语句中出现了死锁

merge into target tt using
(select * from global_tmp_tb) hh
on( hh.pk=tt.pk)
when matched then
 update
when not matched then
 insert


---------Blocker(s)--------  ---------Waiter(s)---------  
process session holds waits  process session holds waits  
   2404    6309     X           2407    6502           S  
   2407    6502     X           2405    6372           S  
   2405    6372     X           1409    4103           S  
   1409    4103     X           2404    6309           S 

Rows waited on:  
  Session 6309: obj - rowid = 0033DA34 - AAM9o0ACfAAOH6cAAA  
  (dictionary objn - 3398196, file - 159, block - 3702428, slot - 0)  
  Session 6502: obj - rowid = 0033D9B0 - AAM9mwACfAAOJaXAAA  
  (dictionary objn - 3398064, file - 159, block - 3708567, slot - 0)  
  Session 6372: obj - rowid = 0033D9B0 - AAM9mwACfAAOJhzAAA  
  (dictionary objn - 3398064, file - 159, block - 3709043, slot - 0)  
  Session 4103: obj - rowid = 0033DDD0 - AAM93QACfAAOLC5AAA  
  (dictionary objn - 3399120, file - 159, block - 3715257, slot - 0) 

合并插入很可能会导致死锁,所以说它的更新

特别是,它正在等待S锁,这是一个共享锁。 但是,如果它在更新时陷入僵局,那为什么它不是互斥锁呢?

这些都是什么意思

  Session 4103: obj - rowid = 0033DDD0 - AAM93QACfAAOLC5AAA  
  (dictionary objn - 3399120, file - 159, block - 3715257, slot - 0) 

我需要查询什么数据字典对象

1 个答案:

答案 0 :(得分:1)

锁定非常复杂,我承认有很多我不了解的内容。 MERGESELECT语句(USING子句)与INSERT和/或UPDATE语句的组合。我的猜测是:

  1. 共享(S)锁是那些以非独占方式锁定行的会话,因为它们已经在语句的MERGE子句中检查了表中USING的源数据。
  2. 排他(X)锁用于在表上进行的更新。

所以我认为基本上正在发生的事情是

  1. 会话A在global_tmp_tb中获取源数据并将行锁定为共享模式。
  2. 会话B在global_tmp_tb中获取源数据,并将行锁定为共享模式。由于共享模式不是排他性的,因此两个会话都可以都具有共享行锁,这没有问题。
  3. 会话A基于ON子句更新第1行。这将在该行上获得排他锁。
  4. 会话B根据ON子句更新第2行。这将在该行上获得排他锁。
  5. 会话A尝试更新第2行。不能这样做,因为会话B将其锁定在行专用模式下。
  6. 会话B尝试更新第1行。之所以不能这样做,是因为会话A将其锁定在行专用模式下。
  7. 景气,僵局。

您真的需要为所有这些会话获取global_tmp_tb中的每个表吗?您可以使用WHERE子句来缩小每个会话的源数据吗?

您可以在select * from global_tmp_tb for update之前MERGE来解决此问题吗?这将意味着对合并的访问将被序列化,并且每个会话都必须按顺序进行,这可能很糟糕。