222

为什么我在更新表时收到此数据库错误?

第 1 行出现错误:ORA-00054:资源繁忙并使用指定的 NOWAIT 获取或超时过期

4

15 回答 15

256

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

于 2011-01-30T12:02:20.877 回答
115

从这里开始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;
于 2012-08-10T03:29:24.090 回答
74

请终止 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';)

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

于 2014-02-10T11:01:08.063 回答
16

这个问题有一个非常简单的解决方法。

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

锁定表'TABLE_NAME'没有等待

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

特别说明:

如果您正在拆分/删除分区,oracle 只需锁定分区。-- 这样你就可以锁定分区子分区。

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

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

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

我在从作业运行的代码中使用它来删除分区。它工作正常。它位于以每秒数百次插入的速度不断插入的数据库中。没有错误。

如果你想知道。在 11g 中执行此操作。我以前也在 10g 中做过这个。

于 2013-04-29T21:15:21.750 回答
14

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

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

找到 SID,

SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
于 2013-07-15T08:28:43.457 回答
12

就我而言,我很确定这是我自己的会话之一阻塞了。因此,执行以下操作是安全的:

  • 我发现了有问题的会话:

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

    会话处于非活动状态,但它仍然以某种方式保持锁定。请注意,您可能需要在您的情况下使用其他一些WHERE条件(例如尝试USERNAMEMACHINE字段)。

  • 使用上面获取的IDSERIAL#获取的会话终止了会话:

    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'
于 2013-09-03T10:27:07.337 回答
9

当用于更改表的会话以外的会话可能由于 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);

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

于 2013-07-15T19:49:57.587 回答
8

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#';

于 2019-09-26T17:52:14.570 回答
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;

然后杀

ALTER SYSTEM KILL SESSION 'sid,serial#'

或者

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

于 2014-11-27T03:30:13.377 回答
5

如其他答案中所述,此错误是由其他会话中运行的并发 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 上的官方文档

于 2021-08-27T18:40:45.243 回答
4

您的问题看起来像是在混合 DML 和 DDL 操作。请参阅解释此问题的此 URL:

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

于 2011-05-05T12:37:43.097 回答
4

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

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

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

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

于 2017-05-23T19:46:27.480 回答
3

简单地创建表时,我设法遇到了这个错误!显然,在一张尚不存在的表上没有争用问题。该CREATE TABLE语句包含一个CONSTRAINT fk_name FOREIGN KEY引用一个填充良好的表的子句。我不得不:

  • 从 CREATE TABLE 语句中删除 FOREIGN KEY 子句
  • 在 FK 列上创建一个 INDEX
  • 创建 FK
于 2015-11-19T15:05:58.603 回答
-3

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

于 2017-01-17T20:50:27.127 回答
-8

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

做一个备份

create table xxxx_backup as select * from xxxx;

删除所有行

delete from xxxx;
commit;

插入备份。

insert into xxxx (select * from xxxx_backup);
commit;
于 2013-03-27T09:23:41.707 回答