此问题仅发生在数据库用户导入的数据库用户。原始数据库用户不存在此问题。
我在oracle 11.2.0.3版本中遇到死锁,其中参与死锁的两个事务的当前sqls如下:
SELECT /*AApaAA*/ objectid FROM T_DS_0 WHERE objectid = :1 FOR UPDATE
insert /*AApaAA*/ into T_DS_0(OBJECTID) values (:1 )
两个绑定变量都是'AApaAA',它也是主键。它看起来像是单一资源上的死锁。
存在指向该主键的外键(在删除级联上)并且它们被索引。
死锁图如下:
---------Blocker(s)-------- ---------Waiter(s)---------
Resource Name process session holds waits process session holds waits
TX-000c000f-00000322 49 102 X 46 587 X
TX-00070011-00000da4 46 587 X 49 102 S
我不清楚如何在单一资源上发生死锁。确实,插入不会锁定行,而是可能是不同资源的约束,因此理论上如果第一个事务执行锁定约束然后锁定行而另一个会反向行,则死锁理论上是可能的。订单,但我没有看到任何方式如何发生这种情况。从理论上讲,子表可以锁定(插入导致子表上的SX)但是select for update不应该触及子表。
来自oracle的完整跟踪文件位于:https://gist.github.com/milanro/06f9a76a2607a26ac9ba8c91b88639b3
有没有人遇到类似的行为?
其他信息:仅当使用datapump复制db用户时才会出现此问题。原始模式包含在创建主键期间创建的SYS索引。还有一些索引以PRIMARY KEY列开头。然后,Datapump不会在PRIMARY KEY列上创建SYS索引,而是使用以PRIMARY KEY列开头的索引。
当我创建以下数据库对象时,它看起来像是:
create table tbl(objectid varchar2(30),一个整数,主键(objectid));
在tbl上创建索引idx1(objectid,a);
创建了1个表和2个索引。 SYS索引(OBJECTID)和idx1(OBJECTID,A)。 PRIMARY KEY使用SYS索引。
执行datapump si后,在导入端只创建1个表和1个索引,索引为idx1(OBJECTID,A),该索引用于PRIMARY KEY。
这种情况发生在我的数据库架构中,表格为SDMBase。当我在不同的事务中使用INSERT INTO SDMBase ...和SELECT ... FROM SDMBase ... FOR UPDATE我使用相同的OBJECTID时,会发生死锁。在这些事务中执行相同的代码,并且在1个事务中可以如下
1.INSERT (objectid1)
2.SELECT FOR UPDATE (objectid1)
3.INSERT (objectid1)
4.SELECT FOR UPDATE (objectid1)
...
死锁情况发生在第2行和第3行。在我的用例中,当这些事务运行时,带有objectid1的行已经在数据库中,但不必提交。
所以我想那个
step 1. should wait until objectid1 is commited and then fail and lock nothing
step 2. should lock objectid1 or wait if another transaction already locked it
step 3. should fail immediately and lock nothing
...
显然步骤1即使失败,也会暂停PK一段时间,但仅限于数据库中数据库的重复数据库。
这些死锁是罕见的,不能手动重现,我想锁定并不是整个交易,而只是很短的时间。
所以它可以如下:
TX1: 1.INSERT (objectid1) (fails and does not lock)
TX1: 2.SELECT (objectid1) (locks SDMBase)
TX2: 1.INSERT (objectid1) (fails but locks PK)
TX1: 3.INSERT (objectid1) (waits on PK)
TX2: 2.SELECT (objectid1) (waits on SDMBase)
即使我在导入的门户中创建索引为SDMBase(OBJECTID)并让PRIMARY KEY使用它,即使我重新创建另一个索引(OBJECTID,...),它仍然会死锁。所以我认为PK约束检查存在一些问题。
解决此问题的方法是创建SDMBase(OBJECTID),让PRIMARY KEY使用它,然后再次执行数据泵。导入必须分两步执行,第一步是排除索引,第二步只导入索引
11.2.0.3和12.2.0.1
中都会出现此问题