我们的一个合并语句中出现了死锁
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)
我需要查询什么数据字典对象
答案 0 :(得分:1)
锁定非常复杂,我承认有很多我不了解的内容。 MERGE
是SELECT
语句(USING
子句)与INSERT
和/或UPDATE
语句的组合。我的猜测是:
MERGE
子句中检查了表中USING
的源数据。所以我认为基本上正在发生的事情是
global_tmp_tb
中获取源数据并将行锁定为共享模式。global_tmp_tb
中获取源数据,并将行锁定为共享模式。由于共享模式不是排他性的,因此两个会话都可以都具有共享行锁,这没有问题。您真的需要为所有这些会话获取global_tmp_tb
中的每个表吗?您可以使用WHERE
子句来缩小每个会话的源数据吗?
您可以在select * from global_tmp_tb for update
之前MERGE
来解决此问题吗?这将意味着对合并的访问将被序列化,并且每个会话都必须按顺序进行,这可能很糟糕。