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

发布于 2024-10-15 03:20:56 字数 114 浏览 5 评论 0原文

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

第 1 行出现错误: ORA-00054: 资源繁忙并在指定 NOWAIT 的情况下获取或超时已过期

Why am I getting this database error when I update a table?

ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

东风软 2024-10-22 03:20:56

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

Your table is already locked by some query. For example, you may have executed select or update and have not yet committed/rollbacked and fired another select query. Do a commit/rollback before executing your query.

自由如风 2024-10-22 03:20:56

从这里ORA-00054:资源繁忙并指定NOWAIT 获取< /a>

您还可以查找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;

from here ORA-00054: resource busy and acquire with NOWAIT specified

You can also look up the sql,username,machine,port information and get to the actual process which holds the connection

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;
微凉徒眸意 2024-10-22 03:20:56

请终止 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 systemkill session '13,36543';)

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

Please Kill Oracle Session

Use below query to check active session info

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;

kill like

alter system kill session 'SID,SERIAL#';

(For example, alter system kill session '13,36543';)

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

最佳男配角 2024-10-22 03:20:56

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

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

LOCK TABLE 'TABLE_NAME' NO WAIT

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

特别注意:

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

所以...
以下步骤可解决该问题。

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

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

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

如果你想知道。在 11g 中这样做。我以前也曾在 10g 中这样做过。

There is a very easy work around for this problem.

If you run a 10046 trace on your session (google this... too much to explain). You will see that before any DDL operation Oracle does the following:

LOCK TABLE 'TABLE_NAME' NO WAIT

So if another session has an open transaction you get an error. So the fix is... drum roll please. Issue your own lock before the DDL and leave out the 'NO WAIT'.

Special Note:

if you are doing splitting/dropping partitions oracle just locks the partition.
-- so yo can just lock the partition subpartition.

So...
The following steps fix the problem.

  1. LOCK TABLE 'TABLE NAME'; -- you will 'wait' (developers call this hanging). until the session with the open transaction, commits. This is a queue. so there may be several sessions ahead of you. but you will NOT error out.
  2. Execute DDL. Your DDL will then run a lock with the NO WAIT. However, your session has aquired the lock. So you are good.
  3. DDL auto-commits. This frees the locks.

DML statements will 'wait' or as developers call it 'hang' while the table is locked.

I use this in code that runs from a job to drop partitions. It works fine. It is in a database that is constantly inserting at a rate of several hundred inserts/second. No errors.

if you are wondering. Doing this in 11g. I have done this in 10g before as well in the past.

ぇ气 2024-10-22 03:20:56

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

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

查找 SID,

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

This error happens when the resource is busy. Check if you have any referential constraints in the query. Or even the tables that you have mentioned in the query may be busy. They might be engaged with some other job which will be definitely listed in the following query results:

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

Find the SID,

SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
若水微香 2024-10-22 03:20:56

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

  • 我发现有问题的会话:

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

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

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

    alter system Kill session ',';

由 @thermz 编辑: 如果前面都没有开放会话查询可以尝试这个。此查询可以帮助您在终止会话时避免语法错误:

  • SELECT 'ALTER SYSTEM KILL SESSION '''||SID||','||SERIAL#||'''立即;'来自 V$SESSION WHERE OSUSER='my_local_username_on_OS'

In my case, I was quite sure it was one of my own sessions which was blocking. Therefore, it was safe to do the following:

  • I found the offending session with:

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

    The session was inactive, but it still held the lock somehow. Note, that you may need to use some other WHERE condition in your case (e.g. try USERNAME or MACHINE fields).

  • Killed the session using the ID and SERIAL# acquired above:

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

Edited by @thermz: If none of the previous open-session queries work try this one. This query can help you to avoid syntax errors while killing sessions:

  • SELECT 'ALTER SYSTEM KILL SESSION '''||SID||','||SERIAL#||''' immediate;' FROM V$SESSION WHERE OSUSER='my_local_username_on_OS'
孤檠 2024-10-22 03:20:56

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

As mentioned in other answers, this error is caused by concurrent DML operations running in other sessions. This causes Oracle to fail to lock the table for DDL with the default NOWAIT option.

For those without admin permissions in the database or who cannot kill/interrupt the other sessions, you can also precede your DDL operation with:

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

I was receiving this error repeatedly in a database with background jobs doing large insert/update operations, and altering this parameter in the session allowed the DDL to continue after a few seconds of waiting for the lock.

For further information, see the comment from rshdev on this answer, this entry on oracle-base or the official docs on DDL_LOCK_TIMEOUT.

悲凉≈ 2024-10-22 03:20:56

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

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

This happens when a session other than the one used to alter a table is holding a lock likely because of a DML (update/delete/insert). If you are developing a new system, it is likely that you or someone in your team issues the update statement and you could kill the session without much consequence. Or you could commit from that session once you know who has the session open.

If you have access to a SQL admin system use it to find the offending session. And perhaps kill it.

You could use v$session and v$lock and others but I suggest you google how to find that session and then how to kill it.

In a production system, it really depends. For oracle 10g and older, you could execute

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

In a separate session but have the following ready in case it takes too long.

alter system kill session '....

It depends on what system do you have, older systems are more likely to not commit every single time. That is a problem since there may be long standing locks. So your lock would prevent any new locks and wait for a lock that who knows when will be released. That is why you have the other statement ready. Or you could look for PLSQL scripts out there that do similar things automatically.

In version 11g there is a new environment variable that sets a wait time. I think it likely does something similar to what I described. Mind you that locking issues don't go away.

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

Finally it may be best to wait until there are few users in the system to do this kind of maintenance.

红ご颜醉 2024-10-22 03:20:56
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#';

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

灼疼热情 2024-10-22 03:20:56

只需检查持有会话的进程并终止它即可。它恢复正常了。

下面的 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';

Just check for process holding the session and Kill it. Its back to normal.

Below SQL will find your process

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;

Then kill it

ALTER SYSTEM KILL SESSION 'sid,serial#'

OR

some example I found online seems to need the instance id as well
alter system kill session '130,620,@1';

烈酒灼喉 2024-10-22 03:20:56

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

  • 一个 SQL*Plus 会话直接使用架构用户帐户(帐户 #1)连接
  • 第一个帐户通过数据库链接进行连接

另一个 SQL*Plus 会话使用不同的架构用户帐户(帐户 #2)连接,但作为我运行的 表删除,然后以帐户#1 创建表。
我对帐户 #2 的会话运行了表更新。没有提交更改。
作为帐户 #1 重新运行表删除/创建脚本。 drop table x 命令出错。

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

I had this error happen when I had 2 scripts I was running. I had:

  • A SQL*Plus session connected directly using a schema user account (account #1)
  • Another SQL*Plus session connected using a different schema user account (account #2), but connecting across a database link as the first account

I ran a table drop, then table creation as account #1.
I ran a table update on account #2's session. Did not commit changes.
Re-ran table drop/creation script as account #1. Got error on the drop table x command.

I solved it by running COMMIT; in the SQL*Plus session of account #2.

悲喜皆因你 2024-10-22 03:20:56

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

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

Your problem looks like you are mixing DML & DDL operations. See this URL which explains this issue:

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

以酷 2024-10-22 03:20:56

我在创建表时就遇到了这个错误!显然,在还不存在的表上不存在争用问题。 CREATE TABLE 语句包含引用填充良好的表的 CONSTRAINT fk_name FOREIGN KEY 子句。我必须:

  • 从 CREATE TABLE 语句中删除 FOREIGN KEY 子句
  • 在 FK 列上创建索引
  • 创建 FK

I managed to hit this error when simply creating a table! There was obviously no contention problem on a table that didn't yet exist. The CREATE TABLE statement contained a CONSTRAINT fk_name FOREIGN KEY clause referencing a well-populated table. I had to:

  • Remove the FOREIGN KEY clause from the CREATE TABLE statement
  • Create an INDEX on the FK column
  • Create the FK
喵星人汪星人 2024-10-22 03:20:56

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

PL/SQL 开发人员
版本 10.0.5.1710

I solved this problem by closing one of my IDE tabs.

PL/SQL Developer
Version 10.0.5.1710

∞琼窗梦回ˉ 2024-10-22 03:20:56

我也面临类似的问题。程序员无需执行任何操作即可解决此错误。我通知了我的 Oracle DBA 团队。他们杀死了会议并发挥了作用。

I also face the similar Issue. Nothing programmer has to do to resolve this error. I informed to my oracle DBA team. They kill the session and worked like a charm.

月依秋水 2024-10-22 03:20:56

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

进行备份

create table xxxx_backup as select * from xxxx;

删除所有行

delete from xxxx;
commit;

插入备份。

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

Solution given by Shashi's link is the best... no needs to contact dba or someone else

make a backup

create table xxxx_backup as select * from xxxx;

delete all rows

delete from xxxx;
commit;

insert your backup.

insert into xxxx (select * from xxxx_backup);
commit;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文