为什么我在更新表时收到此数据库错误?
第 1 行出现错误:ORA-00054:资源繁忙并使用指定的 NOWAIT 获取或超时过期
您的表已被某些查询锁定。例如,您可能已经执行了“select for update”,但尚未提交/回滚并触发另一个选择查询。在执行查询之前执行提交/回滚。
从这里开始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;
请终止 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 跟踪(谷歌这个...太多解释)。您将看到,在任何 DDL 操作之前,Oracle 会执行以下操作:
锁定表'TABLE_NAME'没有等待
所以如果另一个会话有一个打开的事务,你会得到一个错误。所以解决办法是……请打鼓。在 DDL 之前发出您自己的锁并省略“NO WAIT”。
特别说明:
如果您正在拆分/删除分区,oracle 只需锁定分区。-- 这样你就可以锁定分区子分区。
所以......以下步骤解决了这个问题。
当表被锁定时,DML 语句将“等待”或开发人员称之为“挂起”。
我在从作业运行的代码中使用它来删除分区。它工作正常。它位于以每秒数百次插入的速度不断插入的数据库中。没有错误。
如果你想知道。在 11g 中执行此操作。我以前也在 10g 中做过这个。
当资源繁忙时会发生此错误。检查查询中是否有任何引用约束。甚至您在查询中提到的表也可能很忙。他们可能从事其他工作,这些工作肯定会列在以下查询结果中:
SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'
找到 SID,
SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
就我而言,我很确定这是我自己的会话之一阻塞了。因此,执行以下操作是安全的:
我发现了有问题的会话:
SELECT * FROM V$SESSION WHERE OSUSER='my_local_username';
会话处于非活动状态,但它仍然以某种方式保持锁定。请注意,您可能需要在您的情况下使用其他一些WHERE条件(例如尝试USERNAME
或MACHINE
字段)。
使用上面获取的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'
当用于更改表的会话以外的会话可能由于 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);
最后,最好等到系统中的用户很少再进行这种维护。
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#';
只需检查持有会话的进程并杀死它。它恢复正常。
下面的 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';
如其他答案中所述,此错误是由其他会话中运行的并发 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 上的官方文档。
您的问题看起来像是在混合 DML 和 DDL 操作。请参阅解释此问题的此 URL:
当我运行 2 个脚本时发生了这个错误。我有:
我运行了一个表删除,然后作为帐户 #1 创建表。我对帐户#2 的会话进行了表格更新。未提交更改。以帐户 #1 重新运行表删除/创建脚本。drop table x
命令出错。
我通过COMMIT;
在帐户#2 的 SQL*Plus 会话中运行来解决它。
简单地创建表时,我设法遇到了这个错误!显然,在一张尚不存在的表上没有争用问题。该CREATE TABLE
语句包含一个CONSTRAINT fk_name FOREIGN KEY
引用一个填充良好的表的子句。我不得不:
我也面临类似的问题。程序员不需要做任何事情来解决这个错误。我通知了我的 Oracle DBA 团队。他们杀死了会议并像魅力一样工作。
Shashi的链接给出的解决方案是最好的......无需联系dba或其他人
做一个备份
create table xxxx_backup as select * from xxxx;
删除所有行
delete from xxxx;
commit;
插入备份。
insert into xxxx (select * from xxxx_backup);
commit;