ORA-00054:资源繁忙,指定NOWAIT或超时获取

为什么我得到这个数据库错误时,我更新表?

错误在第1行: ORA-00054:资源繁忙,获取时指定了NOWAIT或超时

1287795 次浏览

您的表已经被某个查询锁定。例如,您可能已经执行了“select For update”,但尚未提交/回滚并触发另一个选择查询。在执行查询之前执行一次提交/回滚。

你的问题看起来像你在混合DML &DDL操作。请看这个URL,它解释了这个问题:

http://www.orafaq.com/forum/t/54714/2/

从这里ORA-00054:资源繁忙,指定NOWAIT获取

您还可以查找sql、用户名、机器、端口信息,并获得持有连接的实际进程

SELECT O.OBJECT_NAME, S.SID, S.SERIAL#, P.SPID, S.PROGRAM,S.USERNAME,
S.MACHINE,S.PORT , S.LOGON_TIME,SQ.SQL_FULLTEXT
FROM V$LOCKED_OBJECT L, DBA_OBJECTS O, V$SESSION S,
V$PROCESS P, V$SQL SQ
WHERE L.OBJECT_ID = O.OBJECT_ID
AND L.SESSION_ID = S.SID AND S.PADDR = P.ADDR
AND S.SQL_ADDRESS = SQ.ADDRESS;

Shashi的链接给出的解决方案是最好的…不需要联系dba或其他人

备份

create table xxxx_backup as select * from xxxx;

删除所有行

delete from xxxx;
commit;

插入备份。

insert into xxxx (select * from xxxx_backup);
commit;

这个问题有一个很简单的解决办法。

如果你在会话上运行10046跟踪(谷歌this…太多了,无法解释)。在任何DDL操作之前,Oracle会执行以下操作:

锁定表“table_name”不等待

因此,如果另一个会话有一个打开的事务,就会得到一个错误。所以解决办法是……请击鼓。在DDL之前发出您自己的锁,并省略'NO WAIT'。

特别注意:

如果你正在分割/删除分区oracle只是锁定分区。 你可以锁定分区子分区。< / p > < p >所以…

.

.
  1. 锁定表'表名';你会“等待”(开发者称之为挂起)。直到具有打开事务的会话提交为止。这是一个队列。所以在你之前可能会有几个疗程。但是你不会出错。
  2. 执行DDL。然后DDL将使用NO WAIT运行一个锁。但是,您的会话已经获得了锁。所以你很好。
  3. DDL自动提交。这就释放了锁。

当表被锁定时,DML语句将“等待”或开发人员称之为“挂起”。

我在从作业运行以删除分区的代码中使用了这个功能。它工作得很好。它位于一个以每秒几百个插入的速度不断插入的数据库中。没有错误。

如果你想知道的话。用11g做这个。我以前也用10g做过这个。

当资源繁忙时发生此错误。检查查询中是否有任何引用约束。甚至您在查询中提到的表也可能处于繁忙状态。他们可能正在从事其他工作,这些工作肯定会在以下查询结果中列出:

SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'

找到SID,

SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id

当用于修改表的会话以外的会话持有锁时,就会发生这种情况,可能是因为DML(更新/删除/插入)。如果您正在开发一个新系统,您或您的团队中的某个人很可能会发出更新语句,您可能会在没有太大后果的情况下终止会话。或者,一旦知道谁打开了会话,就可以从该会话提交。

如果您可以访问SQL管理系统,请使用它来查找违规会话。也许还会杀死它。

你可以使用v$session和v$lock等,但我建议你谷歌如何找到该会话,然后如何杀死它。

在生产系统中,这确实取决于情况。对于oracle 10g或更老的版本,您可以执行

LOCK TABLE mytable in exclusive mode;
alter table mytable modify mycolumn varchar2(5);

在一个单独的会议,但准备好以下,以防太长时间。

alter system kill session '....

这取决于你使用的是什么系统,旧的系统更有可能每次都不提交。这是一个问题,因为可能会有长时间的锁。因此,您的锁将阻止任何新的锁,并等待一个不知道何时释放的锁。这就是为什么你准备了另一个声明。或者你也可以寻找可以自动完成类似任务的PLSQL脚本。

在版本11g中,有一个新的环境变量用于设置等待时间。我认为它可能与我所描述的类似。请注意,锁定问题不会消失。

ALTER SYSTEM SET ddl_lock_timeout=20;
alter table mytable modify mycolumn varchar2(5);

最后,最好等到系统中用户较少时再进行这种维护。

在我的情况下,我非常确定它是我自己的疗程阻塞之一。因此,这样做是安全的:

  • 我发现了违规会话:

    SELECT * FROM V$SESSION WHERE OSUSER='my_local_username';

    会话是不活跃的,但它仍然以某种方式持有锁。注意,在你的情况下,你可能需要使用一些其他的在哪里条件(例如,尝试USERNAMEMACHINE字段)

  • 使用上面获得的IDSERIAL#结束会话:

    alter system kill session '<id>, <serial#>'; < / p >

编辑@thermz:如果前面的开放会话查询都不行,试试这个。这个查询可以帮助你在杀死会话时避免语法错误:

  • SELECT 'ALTER SYSTEM KILL SESSION '''||SID||','||SERIAL#||''' immediate;' FROM V$SESSION WHERE OSUSER='my_local_username_on_OS'

请关闭Oracle会话

使用下面的查询来检查活动会话信息

SELECT
O.OBJECT_NAME,
S.SID,
S.SERIAL#,
P.SPID,
S.PROGRAM,
SQ.SQL_FULLTEXT,
S.LOGON_TIME
FROM
V$LOCKED_OBJECT L,
DBA_OBJECTS O,
V$SESSION S,
V$PROCESS P,
V$SQL SQ
WHERE
L.OBJECT_ID = O.OBJECT_ID
AND L.SESSION_ID = S.SID
AND S.PADDR = P.ADDR
AND S.SQL_ADDRESS = SQ.ADDRESS;

杀死像

alter system kill session 'SID,SERIAL#';

(例如,alter system kill session '13,36543';)

< p >参考 http://abeytom.blogspot.com/2012/08/finding-and-fixing-ora-00054-resource.html < / p >

只需检查持有会话的进程并杀死它。一切恢复正常。

在SQL下面可以找到您的流程

SELECT s.inst_id,
s.sid,
s.serial#,
p.spid,
s.username,
s.program FROM   gv$session s
JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id;

然后杀死它

ALTER SYSTEM KILL SESSION 'sid,serial#'

我在网上找到的一些例子似乎也需要实例id

. 0:取消会话

我设法击中这个错误时,只是简单地创建一个表!在一个还不存在的表上,显然不存在争用问题。CREATE TABLE语句包含一个CONSTRAINT fk_name FOREIGN KEY子句,引用一个填充良好的表。我不得不:

  • 从CREATE TABLE语句中删除外键子句
  • 在FK列上创建一个INDEX
  • 创建FK

我也面临着类似的问题。程序员不需要做任何事情来解决这个错误。我通知了我的oracle DBA团队。他们扼杀了会议,并像一个魅力。

我有这个错误发生时,我有2个脚本,我正在运行。我有:

  • SQL*Plus会话直接使用模式用户帐户(帐户#1)连接
  • 另一个SQL*Plus会话使用不同的模式用户帐户(帐户#2)连接,但作为第一个帐户跨数据库链接连接

我运行了一个表删除,然后创建表作为帐户#1。 我对账号2的会话进行了表更新。没有提交更改。 以帐户#1的身份重新运行表删除/创建脚本。

. drop table x命令出错

我通过在帐户#2的SQL*Plus会话中运行COMMIT;来解决它。

select
c.owner,
c.object_name,
c.object_type,
b.sid,
b.serial#,
b.status,
b.osuser,
b.machine
from
v$locked_object a,
v$session b,
dba_objects c
where
b.sid = a.session_id
and
a.object_id = c.object_id;
   

ALTER SYSTEM KILL SESSION 'sid,serial#';

正如在其他回答中提到的,此错误是由在其他会话中运行的并发DML操作引起的。这将导致Oracle无法用默认的NOWAIT选项锁定DDL的表。

对于那些在数据库中没有管理权限或不能杀死/中断其他会话的用户,您还可以在DDL操作之前使用:

alter session set DDL_LOCK_TIMEOUT = 30;
--Run your DDL command, e.g.: alter table, etc.

我在后台作业执行大型插入/更新操作的数据库中反复收到此错误,在会话中更改此参数允许DDL在等待锁几秒钟后继续执行。

有关更多信息,请参阅rshdev对这个答案这是关于oracle-base的条目DDL_LOCK_TIMEOUT的官方文档. xml文件的注释。

我通过关闭一个IDE选项卡解决了这个问题。

< p > PL / SQL开发人员 版本10.0.5.1710 < / p >