ORA-00054:资源繁忙并在指定NOWAIT或超时过期时获取

sun*_*sun 176 oracle ora-00054

我更新表时为什么会出现此数据库错误?

第1行的错误:ORA-00054:资源繁忙并在指定NOWAIT或超时到期时获取

use*_*367 206

您的表已被某些查询锁定.例如,您可能已执行"select for update"并且尚未提交/回滚并触发另一个选择查询.在执行查询之前执行提交/回滚.

  • 我会在那里添加'in another session'.一个常见的情况是你已经在一个工具中测试了更新,比如SQL Developer或Toad,然后尝试在其他地方运行它,而第一个会话仍然保持锁定.因此,您需要提交/回滚其他会话,然后才能再次运行更新. (46认同)
  • 那么,让我遇到这个问题的原因是在Toad:当我想要删除一行时,一位同事和我在同一张桌子上,所以我无法将其删除.当他切换到另一个表时,我能够删除行.它可能会帮助那里的人.但这只有你在桌面内使用Toad而不是查询. (4认同)
  • 最有可能的 DML(插入/删除/更新)而不是查询。在另一个会话中。仅仅因为提出问题的人似乎是新手,答案可能是正确的。但是您不能代表生产系统中的其他用户提交。 (2认同)

小智 94

从这里开始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;
Run Code Online (Sandbox Code Playgroud)

  • 我不得不从查询中删除s.port但它让我找到了罪魁祸首 (4认同)
  • 我遇到了与OP相同的问题,但是看不到您提到的任何表(例如,从V $ LOCKED_OBJECT中选择*,例如,返回ORA-00942:表或视图不存在)。有任何想法吗? (4认同)
  • 您可能没有足够的权限来查看管理视图。 (3认同)

Cha*_*Thu 57

请杀死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;
Run Code Online (Sandbox Code Playgroud)

像杀人一样

alter system kill session 'SID,SERIAL#';
Run Code Online (Sandbox Code Playgroud)

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

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

  • 应该用所需的特权说明这个答案。我拥有自己的帐户,但是具有`CONNECT`和`RESOURCE`,但没有任何需要,并说`ORA-00942:表或视图不存在”。并非每个阅读此线程的人都会拥有`SYS`帐户。 (2认同)

Bob*_*Bob 17

这个问题很容易解决.

如果您在会话中运行10046跟踪(谷歌这...太多无法解释).您将在任何DDL操作之前看到Oracle执行以下操作:

锁定表'TABLE_NAME'没有等待

因此,如果另一个会话具有打开的事务,则会出现错误.所以修复是...滚筒请.在DDL之前发出自己的锁,并省略'NO WAIT'.

特别说明:

如果你正在拆分/删除分区oracle只是锁定分区. - 所以你可以锁定分区子分区.

所以...以下步骤解决了这个问题.

  1. 锁表'表名'; - 你会"等待"(开发人员称之为悬挂).直到与开放事务的会话,提交.这是一个队列.所以你可能会有几个会议.但你不会错.
  2. 执行DDL.然后,您的DDL将以NO WAIT运行锁定.但是,您的会话已获取锁定.所以你很好.
  3. DDL自动提交.这释放了锁.

当表被锁定时,DML语句将"等待"或开发人员将其称为"挂起".

我在从作业到删除分区的代码中使用它.它工作正常.它在数据库中以每秒几百次插入的速率不断插入.没有错误.

如果你想知道.在11g这样做.我之前和以前一样都是以10g完成的.

  • 好的,这是错的.在11g中,使用set_ddl_timeout,这仅在11g中可用.oracle在做DDL之前做了提交,所以它释放了锁.在11g中,您可以让您的DDL等待.我现在正在这样做.工作良好. (3认同)
  • 在11g中你应该使用LOCK TABLE table_name IN EXCLUSIVE MODE; (3认同)
  • @vapcguy 这在 11g 上对我有用:`ALTER SYSTEM SET ddl_lock_timeout=20;` 请参阅[文档](https://docs.oracle.com/database/121/REFRN/GUID-72D43EF8-F7AF-4011-8D64-73ABC4FB2154 .htm#REFRN10267) (2认同)

Aru*_*dan 11

资源繁忙时会发生此错误.检查查询中是否有任何引用约束.或者甚至您在查询中提到的表可能很忙.他们可能会参与其他一些工作,这些工作肯定会列在以下查询结果中:

SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'
Run Code Online (Sandbox Code Playgroud)

找到SID,

SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
Run Code Online (Sandbox Code Playgroud)

  • 并非每个人都能访问这些视图。我收到“ORA-00942:表或视图不存在”。 (2认同)

div*_*ira 8

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

对于那些在数据库中没有管理员权限或无法终止/中断其他会话的人,您还可以在 DDL 操作之前执行以下操作:

alter session set DDL_LOCK_TIMEOUT = 30;
--Run your DDL command, e.g.: alter table, etc.
Run Code Online (Sandbox Code Playgroud)

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

有关更多信息,请参阅 rshdev 对此答案的评论、oracle-base 上的此条目DDL_LOCK_TIMEOUT 上的官方文档


Art*_*dez 7

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

如果您有权访问SQL管理系统,请使用它来查找违规会话.也许杀了它.

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

在生产系统中,它真的取决于.对于oracle 10g及更早版本,您可以执行

LOCK TABLE mytable in exclusive mode;
alter table mytable modify mycolumn varchar2(5);
Run Code Online (Sandbox Code Playgroud)

在一个单独的会话中,如果需要太长时间,请准备好以下内容.

alter system kill session '....
Run Code Online (Sandbox Code Playgroud)

这取决于您拥有的系统,旧系统更有可能不会每次都提交.这是一个问题,因为可能存在长时间锁定.所以你的锁会阻止任何新的锁并等待谁知道什么时候会被释放的锁.这就是你准备另一个声明的原因.或者您可以在那里查找自动执行类似操作的PLSQL脚本.

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

ALTER SYSTEM SET ddl_lock_timeout=20;
alter table mytable modify mycolumn varchar2(5);
Run Code Online (Sandbox Code Playgroud)

最后,最好等到系统中的用户很少进行这种维护.


wry*_*iel 7

就我而言,我非常确定这是我自己的会话中的一个被阻塞。因此,执行以下操作是安全的:

  • 我发现有以下问题:

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

    该会话处于非活动状态,但仍以某种方式锁定了该锁。请注意,您可能需要根据情况使用其他WHERE条件(例如try USERNAMEMACHINEfield)。

  • 使用ID和杀死了以上会话SERIAL#

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

@thermz编辑:如果以前的打开会话查询均不起作用,请尝试执行此操作。此查询可以帮助您避免在杀死会话时避免语法错误:

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


小智 7

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#';
Run Code Online (Sandbox Code Playgroud)


小智 5

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

下面的 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;
Run Code Online (Sandbox Code Playgroud)

然后杀了

ALTER SYSTEM KILL SESSION 'sid,serial#'
Run Code Online (Sandbox Code Playgroud)

或者

我在网上找到的一些示例似乎需要实例 ID 以及更改系统终止会话 '130,620,@1';


vap*_*guy 5

当我运行 2 个脚本时,发生了此错误。我有:

  • 使用架构用户帐户(帐户#1)直接连接的 SQL*Plus 会话
  • 另一个 SQL*Plus 会话使用不同的架构用户帐户(帐户 #2)连接,但作为第一个帐户通过数据库链接进行连接

我运行了表删除操作,然后以帐户 #1 的身份创建了表。我对帐户 #2 的会话运行了表更新。没有提交更改。作为帐户 #1 重新运行表删除/创建脚本。命令出错drop table x

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

  • Shakeer,这只是发生在我身上时我正在做的一个例子 - 不是问题的解决方案 - 那是在我的最后一行 - 运行“COMMIT;”。如果您甚至无法删除表,则您无权更改任何可能导致您首先陷入此问题的内容。 (2认同)