将列更改为非空时避免出现 ORA-00054

Avoiding ORA-00054 when altering column to not null

我想在重度使用 table 上将现有列更改为 "not null" 时避免出现以下或任何其他错误消息:

SQL Error: ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
00054. 00000 -  "resource busy and acquire with NOWAIT specified or timeout expired"
*Cause:    Interested resource is busy.
*Action:   Retry if necessary or increase timeout.

我的 Oracle 版本是:Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production。我按如下方式使用独占锁进行了尝试,但仍然出现错误。我通过在其他会话中执行一些 DML 来模拟大量使用 table。

第 1 节

create table iei1731 (
  col1 varchar2(1 char),
  col2 number(1,0)
);
insert into iei1731 (col1, col2) values ('1', 0);
commit;
update iei1731 set col1 = col1 where col1 = '1';

第 2 节

lock table iei1731 in exclusive mode;

第 1 节

rollback; -- now session 2 gets the exclusive lock on the table
update iei1731 set col1 = col1 where col1 = '1';

第 2 节

alter table iei1731 modify col2 not null; -- here I get the ORA-00054

第 1 节(清理)

rollback;
drop table iei1731;

所以我的问题是,是否有可能在没有任何错误消息的情况下将此重用 table 上的列设置为非空?

如果它被独占锁定 - 否 - 必须先释放锁。

同时进行非空更改是元数据更改,因此如果此对象被频繁访问,您将创建一个可能的 'row cache' 锁,并且该行缓存锁将使其他人在队列中等待对象访问直到你的 not null 成功。这可能会在繁忙的生产环境中导致讨厌的等待滚雪球。最好在停机或不太忙的时候更改元数据。

使用DDL_LOCK_TIMEOUT让会话等待锁:

--Wait up to 10 minutes to acquire the lock.
alter session set DDL_LOCK_TIMEOUT=600;
alter table iei1731 modify col2 not null;