我遇到了这个问题,但尚未找到解决方案:
我有一个包含多个表的应用程序(像大多数应用程序一样)。
其中两个表是:
TB_POLICY
---------
id number(18) : PK
... some other columns
TB_REDEMPTION
-------------
id number(18) : PK
fk_policy number(18) : NOT NULL, FK
... some other columns
TB_POLICY
按部分字段的哈希值进行分区,TB_REDEMPTION
按照fk_policy
关系的引用进行分区。
表TB_POLICY
包含大约50,000条记录,表TB_REDEMPTION
包含大约25,000,000条记录。
有一个用例,其中应用程序在TB_POLICY
中插入单个记录,在TB_REDEMPTION
中在单个事务中插入大量记录(大约200-300条记录)。
当我在代码中标记断点,在所有插入(在两个表中)之后,以及在提交事务之前,没有办法从另一个数据库连接向TB_REDEMPTION
插入另一条记录(甚至直接来自SQL * Plus) - 它只是等待!
我们分析了很多东西,发现PK_REDEMPTION
上发生了锁定(TB_REDEMPTION
的主键索引)。
如何防止此锁定?我在网上搜索过,在插入过程中没有找到关于索引锁的任何内容。
我要提到的是,这个应用程序是基于Web的,并且有许多并发用户使用相同的用例,并且用户锁定主键索引,阻止其他用户的工作,并且对性能有非常糟糕的影响。应用
另一点,应用程序是由Spring / Hibernate开发的,因此事务管理由Spring完成,而DML语句由Hibernate创建。我们正在使用Oracle 11g。
答案 0 :(得分:0)
我已经解决了这个问题,TB_REDEMPTION有另一个外键FK_PAY
,它是唯一但可以为空的。
定义为:
alter table tb_redemption add constraint uk_rdm_pay unique(fk_pay);
但问题是如果所有索引属性都为null,Oracle不会将索引添加到索引中。因此,当插入fk_pay
等于null的记录时,Oracle会锁定表而不是索引中的记录,这是问题的根源。
我通过删除唯一约束并定义以下唯一索引来解决问题:
create unique index ux_rdm_pay on tb_redemption(fk_pay, case when fk_pay is null then id end);
因此唯一索引强制关系的唯一性,并且索引的字段永远不会是null
,因此表中的所有记录都将被编入索引并且它会阻止表锁定。