【问题标题】:Avoiding ORA-00054 when altering column to not null将列更改为非空时避免 ORA-00054
【发布时间】:2017-12-22 02:14:35
【问题描述】:

在将重用表上的现有列更改为“非空”时,我希望避免出现以下错误消息或任何其他错误消息:

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 来模拟一个使用量很大的表。

会话 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;

所以我的问题是,是否有可能将这个重用表上的列设置为不为空而没有任何错误消息?

【问题讨论】:

标签: sql oracle ddl


【解决方案1】:

使用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;

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 但是持有独占锁的是会话 2。然后会话 2 将该列设置为不为空并得到错误。此外,当我删除独占锁定语句时,我得到 ORA-00054。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 2015-12-08
    • 2016-05-02
    相关资源
    最近更新 更多