1

我有这个问题,还没有找到解决方案:

我有一个包含多个表的应用程序(就像大多数应用程序一样)。

其中两个表是:

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和许多记录(大约 200-300 条记录) 。TB_REDEMPTION

TB_REDEMPTION当我在代码中标记断点时,在所有插入之后(在两个表中),并且在提交事务之前,无法从另一个数据库连接(甚至直接从 SQL*Plus)插入另一条记录- 它只是等待!

我们分析了很多东西,发现在PK_REDEMPTION(的主键索引TB_REDEMPTION)上发生了锁。

我怎样才能防止这个锁?我在网上搜索并没有在插入过程中找到任何关于索引锁的信息。

需要提一下,这个应用程序是基于web的,有很多并发用户使用同一个用例,并且一个用户锁定了主键索引,阻止了其他用户的工作,对应用程序的性能影响很差。

还有一点,应用是Spring/Hibernate开发的,所以事务管理是Spring做的,DML语句是Hibernate创建的。我们正在使用 Oracle 11g。

4

1 回答 1

0

我已经解决了这个问题,TB_REDEMPTION 有另一个FK_PAY唯一但可以为空的外键。

它被定义为:

alter table tb_redemption add constraint uk_rdm_pay unique(fk_pay);

但问题是如果所有索引属性都为空,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在一起,所以表中的所有记录都会被索引,它可以防止表锁。

于 2013-12-13T21:57:09.780 回答