ORA-00054: 资源繁忙并指定 NOWAIT 或超时已过期
为什么更新表时会出现此数据库错误?
第 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
您的表已被某些查询锁定。例如,您可能已执行
select
或update
但尚未提交/回滚并触发另一个选择查询。在执行查询之前执行提交/回滚。Your table is already locked by some query. For example, you may have executed
select
orupdate
and have not yet committed/rollbacked and fired another select query. Do a commit/rollback before executing your query.从这里ORA-00054:资源繁忙并指定NOWAIT 获取< /a>
您还可以查找sql、用户名、机器、端口信息并获取持有连接的实际进程
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
请终止 Oracle 会话
使用下面的查询来检查活动会话信息
终止
(例如,
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
kill like
(For example,
alter system kill session '13,36543'
;)Reference
http://abeytom.blogspot.com/2012/08/finding-and-fixing-ora-00054-resource.html
对于这个问题有一个非常简单的解决方法。
如果你在你的会话中运行 10046 跟踪(谷歌这个......太多解释)。您将看到,在任何 DDL 操作之前,Oracle 都会执行以下操作:
LOCK TABLE 'TABLE_NAME' NO WAIT
因此,如果另一个会话有一个打开的事务,您会收到错误。所以解决办法是……请击鼓。在 DDL 之前发出您自己的锁并省略“NO WAIT”。
特别注意:
如果您要拆分/删除分区,oracle 只会锁定分区。
-- 这样你就可以锁定分区子分区。
所以...
以下步骤可解决该问题。
当表被锁定时,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.
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.
当资源繁忙时会发生此错误。检查查询中是否有任何引用约束。或者甚至您在查询中提到的表也可能很忙。他们可能正在从事其他工作,这些工作肯定会列在以下查询结果中:
查找 SID,
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:
Find the SID,
就我而言,我非常确定这是我自己的会话之一被阻塞。因此,执行以下操作是安全的:
我发现有问题的会话:
SELECT * FROM V$SESSION WHERE OSUSER='my_local_username';
会话不活动,但它仍然以某种方式保持锁定。请注意,您可能需要在您的情况下使用其他WHERE条件(例如尝试
USERNAME
或MACHINE
字段)。使用上面获取的
ID
和SERIAL#
终止会话: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
orMACHINE
fields).Killed the session using the
ID
andSERIAL#
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'
正如其他答案中提到的,此错误是由在其他会话中运行的并发 DML 操作引起的。这会导致 Oracle 无法使用默认的 NOWAIT 选项锁定 DDL 表。
对于那些在数据库中没有管理员权限或无法终止/中断其他会话的人,您还可以在 DDL 操作之前执行以下操作:
我在后台作业执行大量插入/更新操作并更改此参数的数据库中反复收到此错误会话中允许 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:
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.
当用于更改表的会话以外的会话可能由于 DML(更新/删除/插入)而持有锁时,就会发生这种情况。如果您正在开发一个新系统,您或您团队中的某人很可能会发出更新语句,并且您可以终止会话而不会产生太大后果。或者,一旦您知道谁打开了会话,您就可以从该会话进行提交。
如果您有权访问 SQL 管理系统,请使用它来查找有问题的会话。或许还可以杀死它。
你可以使用 v$session 和 v$lock 等,但我建议你谷歌如何找到该会话,然后如何杀死它。
在生产系统中,这确实取决于。对于 oracle 10g 及更早版本,您可以
在单独的会话中执行,但请准备好以下内容,以防花费太长时间。
这取决于您拥有什么系统,较旧的系统更有可能不会每次都提交。这是一个问题,因为可能存在长期存在的锁。所以你的锁会阻止任何新的锁并等待一个不知道什么时候会被释放的锁。这就是为什么你要准备好另一份声明。或者您可以寻找自动执行类似操作的 PLSQL 脚本。
在版本 11g 中,有一个新的环境变量用于设置等待时间。我认为它可能会做与我所描述的类似的事情。请注意,锁定问题不会消失。
最后,最好等到系统中的用户很少时再进行此类维护。
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
In a separate session but have the following ready in case it takes too long.
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.
Finally it may be best to wait until there are few users in the system to do this kind of maintenance.
只需检查持有会话的进程并终止它即可。它恢复正常了。
下面的 SQL 会找到你的进程
然后杀死它
或者
我在网上找到的一些例子似乎也需要实例 ID
更改系统终止会话'130,620,@1';
Just check for process holding the session and Kill it. Its back to normal.
Below SQL will find your process
Then kill it
OR
some example I found online seems to need the instance id as well
alter system kill session '130,620,@1';
当我运行 2 个脚本时,发生了此错误。我有:
另一个 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:
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.您的问题看起来像是您正在混合 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/
我在创建表时就遇到了这个错误!显然,在还不存在的表上不存在争用问题。
CREATE TABLE
语句包含引用填充良好的表的CONSTRAINT fk_name FOREIGN KEY
子句。我必须: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 aCONSTRAINT fk_name FOREIGN KEY
clause referencing a well-populated table. I had to:我通过关闭一个 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
我也面临类似的问题。程序员无需执行任何操作即可解决此错误。我通知了我的 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.
Shashi 的链接给出的解决方案是最好的...无需联系 dba 或其他人
进行备份
删除所有行
插入备份。
Solution given by Shashi's link is the best... no needs to contact dba or someone else
make a backup
delete all rows
insert your backup.