ORA-00054 : 자원이 바쁘고 NOWAIT가 지정되어 있거나 타임 아웃이 만료 된 취득


193

테이블을 업데이트 할 때이 데이터베이스 오류가 발생하는 이유는 무엇입니까?

1 행의 오류 : ORA-00054 : 자원이 사용 중이며 NOWAIT를 지정하여 획득하거나 시간 종료가 만료되었습니다


22
일반적으로 오류로 이어지는 진술을 게시하면 도움이됩니다
Gary Myers

답변:


222

테이블이 이미 일부 쿼리에 의해 잠겨 있습니다. 예를 들어 "업데이트를 위해 선택"을 실행했지만 아직 다른 선택 쿼리를 커밋 / 롤백하지 않고 시작했을 수 있습니다. 쿼리를 실행하기 전에 커밋 / 롤백을 수행하십시오.


47
나는 '다른 세션에'를 추가 할 것입니다. 일반적인 시나리오 중 하나는 SQL Developer 또는 Toad와 같은 도구에서 업데이트를 테스트 한 다음 첫 번째 세션이 여전히 잠금을 유지하는 동안 다른 곳에서 실행을 시도한 것입니다. 따라서 업데이트를 다시 실행하기 전에 다른 세션을 커밋 / 롤백해야합니다.
Alex Poole

1
쿼리가 아닌 DML (삽입 / 삭제 / 업데이트) 일 가능성이 높습니다. 그리고 다른 세션에서. 요청한 사람이 초보자 인 것처럼 보이기 때문에 정답 일 수 있습니다. 그러나 프로덕션 시스템에서 다른 사용자를 대신하여 커밋 할 수 없습니다.
Arturo Hernandez

4
글쎄, 그 문제를 일으킨 것은 Toad에서였습니다. 동료는 행을 삭제하려고 할 때와 같은 테이블에 있었고 삭제할 수 없었습니다. 그가 다른 테이블로 전환했을 때 나는 행을 삭제할 수있었습니다. 아마도 누군가를 도울 수 있습니다. 그러나 이것은 테이블 내에서 Toad를 사용하는 경우에만 해당되며 쿼리에는 적용되지 않습니다.
DatRid

최근 스테이징 서버 (WebSphere의 Spring 애플리케이션)에서 발생했습니다. 해결책은 오류 발생 문을 별도의 트랜잭션을 사용하는 별도의 업데이트 서비스로 이동하여 "단일"데이터베이스 업데이트 스크립트를 작은 조각으로 분리하는 것입니다. @Transactional (propagation = Propagation.REQUIRES_NEW)
actc

103

여기에서 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;

5
쿼리에서 s.port를 제거해야했지만 범인을 찾을 수있게되었습니다
Sibster

잠금은 일시적입니다. 삽입이 오면 즉시 커밋합니다. 이 쿼리에는 표시되지 않습니다. 'DDL'을 발행해도 여전히 오류가 발생할 수 있습니다. 거래가 열려있는 동안. 아래 내 게시물을 참조하십시오. 이것은 정말 해결하기 쉽습니다.
Bob

4
OP와 동일한 문제가 있지만 언급 한 테이블을 볼 수 없습니다 (예 : V $ LOCKED_OBJECT를 선택하십시오 (예 : ORA-00942를 반환합니다 : 테이블 또는 뷰가 존재하지 않음)). 어떤 아이디어?
random_forest_fanatic

3
관리 뷰를 볼 수있는 권한이 없을 수 있습니다.
njplumridge

S.Port문제 에 대한 후속 조치 :의 11.2 문서 언급 Port은 필드 V$Session이지만 11.1을 사용하는 S.Port경우 유효하지 않습니다. 11.2에 추가 되었습니까?

64

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


5
어떤 특권이 필요한지이 답변에주의해야합니다. 나는이 CONNECTRESOURCE내가 가지고, 다음과 같이 말한다 계정으로, 어떤이 요구를하지만 ORA-00942: table or view does not exist. 이 글을 읽는 모든 사람이 SYS계정 을 가지고있는 것은 아닙니다 .
vapcguy

선택 열 'S.OSUSER'도 추가하면 해당 트랜잭션을 실행중인 사용자를 알 수 있으며 세션을 종료하기 전에 사용자와 확인하려는 경우에 유용합니다.
Narasimha 2016 년

세션이 중단 alter system kill session '13,36543'되면 시간이 초과되고 세션이 종료되지 않습니다. 이 경우 다음을 참조하십시오 : stackoverflow.com/a/24306610/587365
Andrew Spencer

connection objectin을 사용하여 테이블에 데이터를 삽입하는 동안 python오류가 발생했습니다. 그런 python script다음가 제대로 닫히지 않고 닫힙니다 connection object. 이제 다른 세션에서 테이블을 삭제하려고하면 "LOCKWAIT"오류가 발생합니다. 내가 시도 할 때 kill session충분한 권한이 없습니다. 이것을 제거하기 위해 다른 무엇을 할 수 있습니까?
sjd

17

이 문제에 대한 매우 쉬운 해결 방법이 있습니다.

세션에서 10046 추적을 실행하면 (Google이 설명하기에는 너무 많습니다). DDL 작업 전에 Oracle이 다음을 수행함을 알 수 있습니다.

LOCK TABLE 'TABLE_NAME'NO WAIT

따라서 다른 세션에 열린 트랜잭션이 있으면 오류가 발생합니다. 그래서 수정은 ... 드럼 롤주세요. DDL 전에 자신의 잠금 장치를 발행하고 'NO WAIT'을 ​​생략하십시오.

특별 참고 사항 :

파티션 분할 / 삭제를 수행하는 경우 oracle은 파티션을 잠급니다. 따라서 파티션 하위 파티션을 잠글 수 있습니다.

그래서 ... 다음 단계는 문제를 해결합니다.

  1. 잠금 테이블 '표 이름'; -당신은 '기다릴 것입니다 (개발자들은 이것을 교수형이라고 부릅니다). 열린 트랜잭션 세션이 커밋 될 때까지 이것은 대기열입니다. 그래서 몇 번의 세션이있을 수 있습니다. 그러나 오류가 발생하지 않습니다.
  2. DDL을 실행하십시오. 그런 다음 DDL은 NO WAIT로 잠금을 실행합니다. 그러나 세션이 잠금을 요청했습니다. 그래서 당신은 좋습니다.
  3. DDL 자동 커밋 잠금이 해제됩니다.

테이블이 잠겨있는 동안 DML 문은 '대기'하거나 개발자가이를 '멈춤'이라고합니다.

작업에서 실행되어 파티션을 삭제하는 코드에서 이것을 사용합니다. 잘 작동합니다. 초당 수백 번의 삽입 속도로 지속적으로 삽입되는 데이터베이스에 있습니다. 오류가 없습니다.

궁금하다면 11g에서이 작업을 수행합니다. 나는 과거에도 10g 전에 이것을했습니다.


3
알았어, 이건 잘못이야 11g에서는 set_ddl_timeout을 사용하십시오. 11g에서만 사용 가능합니다. oracle은 DDL을 수행하기 전에 커밋을 수행하므로 잠금을 해제합니다. 11g에서는 DDL을 기다릴 수 있습니다. 지금하고 있습니다. 잘 작동합니다.
Bob

3
11g에서는 LOCK TABLE table_name IN EXCLUSIVE MODE를 사용해야합니다.
Kamil Roman

1
이것은 배치 작업에서 ORA-00054를 얻는 경우 실제로 유용하지만 (OP 및 나와 포함하여) 여기에 도착하는 대부분의 사람들이 개발 중이며 동일한 테이블에서 삽입을 수행하여 세션을 열어 두었다고 생각합니다. 삭제하고 다시 만들려고합니다. KILL SESSION이 사람들에게 정답입니다.
앤드류 스펜서

@Bob 11g와 이전 방식의 예제 코드가 좋을 것입니다. 구문은 set_ddl_timeout무엇이며 어떤 형식이어야합니까?
vapcguy

1
11g에 나를 위해 일한이 @vapcguy : ALTER SYSTEM SET ddl_lock_timeout=20;참조 문서
rshdev

13

이 오류는 리소스가 사용 중일 때 발생합니다. 조회에 참조 제한 조건이 있는지 확인하십시오. 또는 쿼리에서 언급 한 테이블도 사용 중일 수 있습니다. 그들은 다음과 같은 쿼리 결과에 분명히 나열된 다른 작업과 관련이있을 수 있습니다.

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

SID를 찾으십시오.

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

1
모든 사람이 이러한 견해에 접근 할 수있는 것은 아닙니다. 나는 얻는다 ORA-00942: table or view does not exist.
vapcguy

이 경우 DB 관리자는 해당 정보를 제공해야합니다.
Arunchunaivendan

항상 그런 것은 아닙니다. 나는 이것을 알아 내고 해결하기 위해 코드를 작성해야했고, 나도 내 서비스 계정도 이러한 권리를 갖지 않을 것입니다.
vapcguy

7

이것은 테이블을 변경하는 데 사용 된 세션 이외의 세션이 DML (업데이트 / 삭제 / 삽입)로 인해 잠금을 보유하고있을 때 발생합니다. 새 시스템을 개발하는 경우 사용자 나 팀의 누군가가 업데이트 문을 발행하고 큰 결과없이 세션을 종료 할 수 있습니다. 또는 누가 세션을 열 었는지 알면 해당 세션에서 커밋 할 수 있습니다.

SQL 관리 시스템에 액세스 할 수 있으면 해당 시스템을 사용하여 위반 세션을 찾으십시오. 그리고 아마 그것을 죽일.

v $ session 및 v $ lock 등을 사용할 수는 있지만 Google에서 해당 세션을 찾는 방법과 종료 방법을 제안합니다.

프로덕션 시스템에서는 실제로 다릅니다. 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);

마지막으로 시스템에 이런 종류의 유지 관리를 수행 할 사용자가 거의 없을 때까지 기다리는 것이 가장 좋습니다.


alter system kill session '....관리 뷰에 액세스 할 수없는 경우 종료 할 세션을 어떻게 찾을 수 있습니까?
vapcguy


7

내 경우에는 차단 된 세션 중 하나라고 확신했습니다 . 따라서 다음을 수행하는 것이 안전했습니다.

  • 나는 다음과 같은 위반 세션을 발견했다.

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

    세션이 비활성 상태 였지만 여전히 잠금을 유지했습니다. 귀하의 경우에 다른 WHERE 조건 을 사용해야 할 수도 있습니다 (예 : try USERNAME또는 MACHINEfield).

  • 을 사용해서 세션을 살해 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'

이전 오픈 세션 쿼리가 작동하지 않으면이 쿼리를 시도하십시오.
thermz

5

세션을 유지하는 프로세스를 확인하고 종료하십시오. 다시 정상으로 돌아 왔습니다.

아래 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'이 필요한 것으로 보입니다.



4

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


3

단순히 테이블을 만들 때이 오류가 발생했습니다! 아직 존재하지 않는 테이블에는 분명히 경합 문제가 없었습니다. 이 CREATE TABLE문에는 CONSTRAINT fk_name FOREIGN KEY잘 채워진 테이블을 참조 하는 절이 포함되어 있습니다. 나는해야했다 :

  • CREATE TABLE 문에서 FOREIGN KEY 절을 제거하십시오.
  • FK 열에 INDEX 생성
  • FK 만들기

방금 같은 문제가있었습니다. ddl 문에서 fk 정의를 제거한 후 테이블을 만들 수 있었지만 열에서 인덱스를 만든 후에도 테이블을 추가 할 수 없습니다.
vadipp

나는 그것을 해결할 수있었습니다. 먼저에 novalidate절을 추가했습니다 alter table add constraint. 이것은 어떻게 든 실행할 수 있지만 잠 깁니다. 그런 다음 세션 잠금을 살펴보고 어떤 세션이 잠겨 있는지 확인했습니다. 그리고 나는 그 세션을 죽였습니다.
vadipp

3

내가 실행중인 2 개의 스크립트가있을 때이 오류가 발생했습니다. 나는했다 :

  • 스키마 사용자 계정 (계정 # 1)을 사용하여 직접 연결된 SQL * Plus 세션
  • 다른 스키마 사용자 계정 (계정 # 2)을 사용하여 연결했지만 데이터베이스 링크를 통해 첫 번째 계정으로 연결하는 다른 SQL * Plus 세션

테이블 삭제를 실행 한 다음 계정 만들기로 테이블 생성을 실행했습니다. 계정 # 2의 세션에서 테이블 업데이트를 실행했습니다. 변경 사항을 커밋하지 않았습니다. 계정 삭제로 테이블 삭제 / 작성 스크립트를 다시 실행하십시오. drop table x명령 에 오류가 있습니다 .

COMMIT;계정 # 2의 SQL * Plus 세션에서 실행 하여 문제를 해결했습니다 .


테이블을 삭제할 권한이 없으면 어떻게해야합니까? 나쁜 답변
Shakeer Hussain

1
셰이커, 그것은 내가 문제를 해결할 수있는 해결책이 아니라 내가 나에게 일어날 때했던 일의 예일뿐입니다 COMMIT;. 테이블을 삭제할 수없는 경우에는 처음에이 문제에 영향을 줄 수있는 항목을 변경할 권한이 없습니다.
vapcguy

-2

나는 또한 비슷한 문제에 직면 해있다. 이 오류를 해결하기 위해 프로그래머가 할 일은 없습니다. 오라클 DBA 팀에 알 렸습니다. 그들은 세션을 죽이고 매력처럼 일했습니다.


1
누군가는 여전히 무언가를해야합니다. DBA 팀이해야 할 일을 모르고 세션을 종료하는 방법은 무엇입니까? 나쁜 대답입니다.
vapcguy

1
DBA가 세션을 죽이는 방법을 모른다면 그는 일하기에 부적합합니다
Shakeer Hussain

문법 오류를 피하기 위해 때때로 구문을 새로 고쳐야합니다.
vapcguy

-5

Shashi의 링크가 제공하는 솔루션이 가장 좋습니다 ... dba 또는 다른 사람에게 연락 할 필요가 없습니다.

백업하다

create table xxxx_backup as select * from xxxx;

모든 행을 삭제

delete from xxxx;
commit;

백업을 삽입하십시오.

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

10
삭제 / 잘라내 기는 서로 호환되지 않습니다. 많은 수의 삭제를 수행하면 성능에 큰 영향을 미칩니다. 이것은 정말 나쁘다.
Bob

나는 이것이 일반적인 패턴이라고 생각했다.
Shawn Xue
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.