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

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


当前回答

请关闭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

其他回答

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

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

锁定表“table_name”不等待

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

特别注意:

如果你正在分割/删除分区,oracle只是锁定分区。 你可以锁定分区子分区。

所以… 下面的步骤可以解决这个问题。

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

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

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

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

选择 c.owner, c.object_name, c.object_type, b.sid, b.serial #, b.status, b.osuser, b.machine 从 v locked_object美元, v $ b会话, dba_objects c 在哪里 B.sid = a.session_id 而且 A.object_id = c.object_id; 删除系统会话的sid

正如在其他回答中提到的,此错误是由在其他会话中运行的并发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的官方文档。

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

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

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