Question

I have this problem, and has not found a solution for it yet:

I have a application with multiple tables (like most applications).

Two of the tables are:

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

The TB_POLICY is partitioned by hash of some of its fields, and TB_REDEMPTION is partitioned by reference on fk_policy relation.

Table TB_POLICY contains about 50,000 records and table TB_REDEMPTION contains about 25,000,000 records.

There is a use-case in which the application inserts a single record in TB_POLICY and lots of records (about 200-300 records) in TB_REDEMPTION in a single transaction.

When I mark a break-point in my code, after all the inserts (in both tables), and before committing the transaction, there is no way to insert another record into TB_REDEMPTION from another database connection (even directly from SQL*Plus) - it just waits!

We analyzed many things and found out that a lock is happened on PK_REDEMPTION (primary key index of the TB_REDEMPTION ).

How can I prevent this lock? I searched the web and did not find anything about an index lock during insert.

I shall mention that this application is web-based and there are many concurrent users using the same use-case, and locking the primary key index by a user, prevents other users' job, and has a very bad performance effect on application.

Another point, the application is developed by Spring/Hibernate, so transaction management is done by Spring, and DML statements are created by Hibernate. And we are using Oracle 11g.

Was it helpful?

Solution

I have solved the problem, the TB_REDEMPTION had another foreign key FK_PAY which was unique but nullable.

It was defined as:

alter table tb_redemption add constraint uk_rdm_pay unique(fk_pay);

But the problem is Oracle does not add record to index if all of index properties are null. So when inserting a record with fk_pay equals to null, Oracle locked the table not the record in index, and that was root of problem.

I solved the problem by dropping the unique constraint and defining following unique index:

create unique index ux_rdm_pay on tb_redemption(fk_pay, case when fk_pay is null then id end);

So the unique index mandates the uniqueness of the relationship, and the index's fields will never be null together, so all records in table would be indexed and it prevents table lock.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top