ORA-00054: ocupado com o recurso e adquirido com o NOWAIT especificado ou expirou o tempo-limite
Porque estou a obter este erro de base de dados quando actualizo uma tabela?
erro na linha 1: ORA-00054: o recurso ocupado e adquirido com o NOWAIT especificado ou o tempo-limite expirado
13 answers
A sua mesa já está bloqueada por alguma consulta. Como você executou "select for update" e ainda não se comprometeu/rollback e novamente disparou select query. Faça um commit/rollback antes de executar a sua pesquisa.
A partir daqui ORA-00054: o recurso está ocupado e adquire com o NOWAIT indicado
Você também pode procurar o sql,nome de utilizador,máquina, informação de porta e chegar ao processo real que detém a conexão
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;
Usar a pesquisa abaixo para verificar a informação da sessão activa
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;
Matar como
alter system kill session 'SID,SERIAL#';
(por exemplo, alter system kill session '13,36543'
;)
Referência http://abeytom.blogspot.com/2012/08/finding-and-fixing-ora-00054-resource.html
Se você executar um trace 10046 na sua sessão (google isto... too much to explain). Você verá que antes de qualquer operação DDL Oracle faz o seguinte:
BLOQUEAR A TABELA 'TABLE_NAME' NO WAIT
Se outra sessão tiver uma transacção aberta, obtém-se um erro. Então a solução é... tambores, por favor. Emite a tua própria fechadura perante o DDL e deixa de fora o "não esperar".
Nota Especial:
Se estiver a fazer dividir / largar partições oráculo apenas bloqueia a partição. -- podes bloquear a subparte da partição.
Então..... Os seguintes passos resolvem o problema.- bloquear a tabela 'nome da tabela'; -- você irá ' esperar '(os programadores chamam a isto enforcamento). até a sessão com a transação aberta, commits. Isto é uma fila. então, pode haver várias sessões à sua frente. mas não te enganarás.
- executar o DDL. O seu DDL irá então abrir uma fechadura sem esperar. No entanto, a sua a sessão requisitou a fechadura. Então és bom.
- DDL auto-commits. Isto liberta as fechaduras.
As declarações DML irão ' esperar 'ou como os programadores lhe chamam' pendurar ' enquanto a tabela está bloqueada.
Uso isto em código que vai de um trabalho para largar partições. Funciona bem. Está em um banco de dados que está constantemente inserindo a uma taxa de várias centenas de inserções/segundo. Sem erros.Se está a pensar. Fazendo isso em 11g. eu já fiz isso em 10g antes também no passado.
Este erro acontece quando o recurso está ocupado. Verifique se você tem quaisquer restrições de referência na consulta. Ou mesmo as tabelas que você mencionou na consulta podem estar ocupadas. Eles podem estar envolvidos com algum outro trabalho que será definitivamente listado nos seguintes resultados da consulta:
SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'
Encontra o SID,
SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
Isto acontece quando uma sessão diferente da usada para alterar uma tabela está a segurar um bloqueio, provavelmente devido a um DML (actualizar/apagar/inserir). Se você está desenvolvendo um novo sistema, é provável que você ou alguém em sua equipe emite a declaração de atualização e você poderia matar a sessão sem muitas consequências. Ou você pode se comprometer a partir dessa sessão uma vez que você sabe quem tem a sessão aberta.
Se tiver acesso a um sistema de administração SQL use-o para encontrar a sessão ofensiva. E talvez matar ele.
Você poderia usar a sessão V$E V$lock e outros, mas eu sugiro que você google como encontrar essa sessão e, em seguida, como matá-lo.
Num sistema de produção, depende. Para oracle 10g e mais velho, você poderia executarLOCK TABLE mytable in exclusive mode;
alter table mytable modify mycolumn varchar2(5);
Numa sessão separada, mas tenha o seguinte pronto, caso demore muito tempo.
alter system kill session '....
Depende do sistema que você tem, os sistemas mais antigos são mais propensos a não se comprometer de todas as vezes. Isso é um problema, uma vez que pode haver muito tempo fechaduras em pé. Por isso, a sua fechadura evitaria novas fechaduras e esperaria por uma fechadura que sabe-se lá quando será libertada. É por isso que tem a outra declaração pronta. Ou você pode procurar por scripts PLSQL lá fora que fazem coisas semelhantes automaticamente.
Na versão 11g existe uma nova variável de ambiente que define um tempo de espera. Acho que faz algo semelhante ao que descrevi. Lembre-se que os problemas de bloqueio não desaparecem.
ALTER SYSTEM SET ddl_lock_timeout=20;
alter table mytable modify mycolumn varchar2(5);
Finalmente, talvez seja melhor esperar até lá. são poucos os usuários no sistema para fazer este tipo de manutenção.
O seu problema parece que está a misturar operações DML & DDL. Veja este URL que explica este problema:
Abaixo do SQL encontrará o seu processo
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;
Então mata-o
ALTER SYSTEM KILL SESSION 'sid,serial#'
Ou
Um exemplo que encontrei online parece precisar do ID da instância. alterar a sessão de remoção do sistema'130,620,@1';-
Encontrei a sessão ofensiva com:
SELECT * FROM V$SESSION WHERE OSUSER='my_local_username';
A sessão estava inactiva, mas ainda assim manteve a fechadura de alguma forma. Note que poderá ter de utilizar outros em que condição no seu caso (por exemplo, tente
USERNAME
ouMACHINE
campos). -
Matou a sessão usando o
ID
eSERIAL#
adquirido acima:alter system kill session '<id>, <serial#>';
Consegui acertar este erro ao criar uma tabela! Obviamente não havia nenhum problema de discórdia em uma mesa que ainda não existia. A declaração CREATE TABLE
continha uma cláusula CONSTRAINT fk_name FOREIGN KEY
referente a uma tabela bem povoada. Tive de:
- Remova a cláusula de chave externa da declaração da tabela CREATE
- criar um índice na coluna FK
- criar o FK
- uma sessão SQL * Plus ligada directamente através de uma conta de utilizador schema (conta #1)
- outra sessão SQL * Plus ligada usando uma conta de utilizador diferente do esquema( conta # 2), mas ligando-se através de uma ligação de base de dados como a primeira conta
Eu fiz uma queda de tabela, depois a criação de tabela como conta #1.
Fiz uma actualização da mesa na sessão da conta nº2. Não efectuou alterações.
Mesa de repetição programa drop / creation como conta #1. Ocorreu um erro no comando drop table x
.
Resolvi-o executando COMMIT;
na sessão SQL*Plus da conta #2.
Também Estou perante uma questão semelhante. Nada programador tem que fazer para resolver este erro. Informei a minha equipa oracle DBA. Eles cancelaram a sessão e funcionaram como um encanto.
Faz uma cópia de segurança
create table xxxx_backup as select * from xxxx;
Apagar todas as linhas
delete from xxxx;
commit;
Insira a sua cópia de segurança.
insert into xxxx (select * from xxxx_backup);
commit;