【问题标题】:Oracle locks index on multiple insertsOracle 在多次插入时锁定索引
【发布时间】:2013-11-26 22:29:57
【问题描述】:

我有这个问题,还没有找到解决办法:

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

其中两个表是:

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_REDEMPTIONfk_policy 关系上的引用分区。

TB_POLICY 包含约 50,000 条记录,表 TB_REDEMPTION 包含约 25,000,000 条记录。

有一个用例,其中应用程序在单个事务中在TB_POLICY 中插入一条记录,在TB_REDEMPTION 中插入大量记录(大约 200-300 条记录)。

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

我们分析了很多东西,发现PK_REDEMPTIONTB_REDEMPTION的主键索引)发生了锁。

如何防止这种锁定?我在网上搜索并没有在插入期间找到任何关于索引锁的信息。

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

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

【问题讨论】:

  • 你确定你的 FK 上有索引吗?您是否启用了休眠跟踪以准确查看正在执行的 SQL 语句?
  • 是的,FK 上有索引。
  • 有很多 SQL 语句(主要是选择),包括 TB_POLICY 上的 1 个插入语句和 TB_REDEMPTION 上的数百个插入语句,以及 TB_REDEMPTION 的子表上的数百个.

标签: oracle hibernate indexing database-partitioning database-locking


【解决方案1】:

我已经解决了这个问题,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在一起,所以表中的所有记录都会被索引并防止表锁定。

【讨论】:

  • 我会考虑使用更简单的索引定义:(fk_pay, 0)。当然,这也永远不会为空,但优化器也意识到了这一点。
  • 那哪个更好?
  • (fk_pay, 0) 应该是。
  • @DavidAldridge 但是它不能是唯一索引来强制fk_pay的唯一性
  • 它可能无法推断索引保证包含所有行 - 或者如果表很窄,它可能不如全表扫描有效。添加额外的 0 列可能会改变前者。
猜你喜欢
  • 2013-10-01
  • 2016-11-18
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多