Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, BhagwanSingh.

Asked: December 14, 2016 - 2:52 pm UTC

Last updated: August 08, 2018 - 3:39 pm UTC

Version: 11g

Viewed 10K+ times! This question is

You Asked

Add foreign constraint in child table at a time inserting statement fire in references table(parent table) so inserting query is going to hold, but we want to insert statement and add foreign key constraint parallel.
it is possible or not ?

and Chris said...

So, if you have an uncommitted insert on the parent and attempt to create an FK on the child by default it'll fail as you say.

For example, take these two tables:

create table t1 (
  x int not null primary key
);

create table t2 (
  x int
);


In session 1 run:

SQL> insert into t1 values (1);

1 row created.


And in session 2:

SQL> alter table t2 add constraint fk foreign key (x) references t1(x);
alter table t2 add constraint fk foreign key (x) references t1(x)
            *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired


BOOOM!

Fortunately there is a way around this (at least from 11.2; I haven't checked on earlier releases). Create the FK novalidated:

SQL> alter table t2 add constraint fk foreign key (x) references t1(x) novalidate;


This is blocked until you commit/rollback the insert in session 1. But you can insert new rows in other sessions. In session 3:

SQL> insert into t1 values (2);

1 row created.


So your application can continue. As soon as the first insert commits, the DDL will complete too:

Session 1:

SQL> commit;

Commit complete.


Session 2:

Table altered.

SQL>


Note that a novalidated constraint doesn't check existing rows in the child. So it's possible to have orphaned rows when you do this!

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

This may not always be the case

JimW, August 09, 2017 - 1:39 pm UTC

I'm not convinced that is the only way this error can occur. We develop a product in the Oracle database and run test builds 6 nights a week. The environment is Oracle 12.1.0.2 both Standard Edition and Enterprise Edition on Windows Server 2012 R2. We occasionally get this error when a foreign key is created on an empty table. Since mid-March of this year, we have received this error 8 times during nightly builds. It just happened again last night. 6 builds a week on 2 different databases since March is over 200 builds, so the error comes up in about 4% of our builds. This part of our code has not changed since March 15th.

There has to be another case where this is possible. We have not opened an SR because the time involved would be too high for such an infrequent error.
Chris Saxon
August 09, 2017 - 4:25 pm UTC

What exactly does your code do and what error do you get?

How certain are you there aren't any uncommitted inserts to the parent?

parent table

gh, August 10, 2017 - 5:19 am UTC

Parent table is empty but maybe it is deleted uncommitted. So still uncommitted .
Chris Saxon
August 10, 2017 - 1:50 pm UTC

That could explain it.

Deploying constraints with zero downtime

Sunil, October 10, 2017 - 10:21 am UTC

I need to create FK constraint on ever-transactional database which has no downtime.

I tested in non-prod with novalidate, but it gives ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired. Possibly because parent table always has some or the other DML happening all the time.

With EBR implemented, we expect zero downtime for deploying all our scripts , is there any way to fix this constraint error ?

PS: I tried ALTER SESSION SET ddl_lock_timeout=XX; but it just retries the constraint creation in case of deadlock and not always assures constraint creation.

Connor McDonald
October 10, 2017 - 1:55 pm UTC

Can you elaborate on what you mean by:

"but it just retries the constraint creation in case of deadlock and not always assures constraint creation."

because that is not my understanding of how ddl_lock_timeout works.

...but there is a lock whit a select?

Francesco, August 08, 2018 - 2:45 pm UTC

Hi,
Probably it's the same for my problem.
I use the parent table in a select statement:
select...
from T1...join...T2

In another session, the DBA execute an add constraint to T3 references T2 and he has ORA-00054.

It's the same problem? If yes, why SELECT use a lock?
Chris Saxon
August 08, 2018 - 3:39 pm UTC

What exactly is your DBA doing? Are you sure the query is the only other operation on the tables at the time?