ORA-00054: kaynak meşgul ve belirtilen NOWAIT değeri veya zaman aşımı süresi dolduktan sonra edinme


193

Bir tabloyu güncellediğimde neden bu veritabanı hatasını alıyorum?

Satır 1'deki HATA: ORA-00054: kaynak meşgul ve belirtilen NOWAIT ile edin veya zaman aşımı süresi doldu


22
Hataya yol açan ifadeyi gönderirseniz genellikle yardımcı olur
Gary Myers

Yanıtlar:


222

Tablonuz zaten bir sorgu tarafından kilitlendi. Örneğin, "güncelleme için seç" i çalıştırmış ve henüz başka bir seçme sorgusu taahhüt etmemiş / geri almamış olabilirsiniz. Sorgunuzu çalıştırmadan önce bir taahhüt / geri alma işlemi yapın.


47
Buna 'başka bir oturumda' eklerdim. Yaygın bir senaryo, SQL Developer veya Toad gibi bir araçta güncelleştirmeyi sınamanız ve daha sonra ilk oturum hala kilidi tutarken başka bir yerde çalıştırmayı denemenizdir. Bu nedenle, güncellemeyi tekrar çalıştırmadan önce diğer oturumu tamamlamanız / geri almanız gerekir.
Alex Poole

1
Bir sorgu yerine büyük olasılıkla DML (ekle / sil / güncelle). Ve başka bir oturumda. Sormuş olan adamın bir acemi gibi göründüğü için cevap doğru olabilir. Ancak bir üretim sistemindeki diğer kullanıcılar adına taahhütte bulunamazsınız.
Arturo Hernandez

4
Peki, bana bu sorunu sahip yaptı Toad oldu: Bir meslektaşım ben bir satır silmek istediğimde olduğu gibi aynı tablo vardı ve bu yüzden bunu silemedim. Başka bir masaya geçtiğinde satırları silebilirdim. Belki birisine yardým edebilir. Ancak bu yalnızca Quad ile değil, tabloların içinde Toad ile çalışıyorsanız.
DatRid

kısa bir süre önce hazırlama sunucumuzda (WebSphere'de Spring uygulaması) meydana geldi. Çözüm, hataya neden olan ifadeleri ayrı bir işlem kullanan ayrı bir güncelleme hizmetine taşıyarak "monolitik" veritabanı güncelleme komut dosyasını daha küçük parçalara ayırmaktı: @Transactional (propagation = Propagation.REQUIRES_NEW)
actc

103

buradan ORA-00054: kaynak meşgul ve belirtilen NOWAIT ile edin

Ayrıca sql, kullanıcı adı, makine, port bilgilerini arayabilir ve bağlantıyı tutan gerçek işleme ulaşabilirsiniz

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
Sorgudan s.port kaldırmak zorunda kaldı ama bu suçlu
bulmama

kilitler geçicidir. böylece ek gelirse, hemen taahhüt. bu sorguda görünmez. 'DDL' düzenlerseniz hatayı alabilirsiniz. işlem açıkken. benim yazı aşağıya bakın. bu etrafında çalışmak gerçekten kolaydır.
Bob

4
OP ile aynı sorunu yaşıyorum, ama bahsettiğiniz tabloların hiçbirini göremiyorum (örneğin, V $ LOCKED_OBJECT * seçin, örneğin, ORA-00942 döner: tablo veya görünüm yok). Herhangi bir fikir?
random_forest_fanatic

3
Yönetim görünümlerine bakmak için yeterli ayrıcalığınız olmayabilir.
njplumridge

S.PortSorunun takibi : 11.2 dokümanı Portbir alan olarak belirtiyor V$Session, ancak benim için 11.1'i kullanmak S.Portgeçersiz. Belki 11.2 için eklendi mi?

64

Lütfen Oracle Oturumunu Öldürün

Etkin oturum bilgilerini kontrol etmek için aşağıdaki sorguyu kullanın

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;

gibi öldür

alter system kill session 'SID,SERIAL#';

(Örneğin alter system kill session '13,36543';;)

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


5
Bu cevabı hangi imtiyazlar gerekli olduğu konusunda uyarmalıdır. Ben CONNECTve RESOURCEben var ve diyor hesapla, her neyse bu ihtiyaçları değil ORA-00942: table or view does not exist. Bu konuyu okuyan herkesin SYShesabı olmayacak .
vapcguy

'S.OSUSER' seçim sütununu da eklerseniz, bu işlemi hangi kullanıcının çalıştırdığını bilirsiniz ve oturumu öldürmeden önce kullanıcıyla kontrol etmek istediğinizde kullanışlı olacaktır.
Narasimha

Eğer oturum asılırsa, zaman alter system kill session '13,36543'aşımı olur ve oturum ölmez. Bu durumda bkz. Stackoverflow.com/a/24306610/587365
Andrew Spencer

Kullanarak bir tabloya veri ekleme yaparken bir connection objectde pythoni bazı hata var. Sonra python scriptdüzgün kapatılmadan kapatılır connection object. Şimdi başka bir oturumda tablo bırakmaya çalıştığınızda "LOCKWAIT" hatası alıyorum. Denediğimde kill sessionyeterince privilage yok. Bundan kurtulmak için başka neler yapılabilir?
sjd

17

Bu sorun için çok kolay bir çözüm var.

Oturumunuzda 10046'lık bir iz çalıştırıyorsanız (google bu ... açıklamak için çok fazla). Herhangi bir DDL işleminden önce Oracle'ın aşağıdakileri yaptığını göreceksiniz:

KİLİT TABLOSU 'TABLE_NAME' BEKLEMEZ

Başka bir oturumda açık bir işlem varsa, bir hata alırsınız. Yani düzeltme ... davul silindiri lütfen. DDL'den önce kendi kilidinizi düzenleyin ve 'BEKLEME YOK' seçeneğini bırakın.

Özel not:

bölme / bırakma bölümleri yapıyorsanız oracle sadece bölümü kilitler. - böylece bölüm alt bölümünü kilitleyebilirsiniz.

Yani ... Aşağıdaki adımlar sorunu çözer.

  1. KİLİT TABLOSU 'TABLO ADI'; - 'bekleyeceksiniz' (geliştiriciler bu asılı olarak adlandırır). açık işlem ile oturuma kadar, taahhüt eder. Bu bir kuyruk. önünüzde birkaç oturum olabilir. ancak hata yapmazsınız.
  2. DDL'yi yürütün. DDL'niz daha sonra NO WAIT (Bekleme Yok) düğmesiyle çalışır. Ancak oturumunuz kilidi kazandı. Yani iyisin.
  3. DDL otomatik olarak işler. Bu kilitleri serbest bırakır.

DML ifadeleri 'kilitlenir' veya geliştiriciler tablo kilitliyken buna "askıda kal" der.

Bu bölümleri bırakmak için bir işten çalışan kodda kullanın. İyi çalışıyor. Saniyede birkaç yüz ekleme hızında sürekli olarak eklenen bir veritabanındadır. Hata yok.

Eğer merak ediyorsanız. Bunu 11g'de yapıyoruz. Bunu daha önce de 10g'da yaptım.


3
tamam, bu yanlış. 11g'de set_ddl_timeout kullanın, Bu yalnızca 11g'de mevcuttur. oracle DDL yapmadan önce bir taahhütte bulunur, bu yüzden kilidi serbest bırakır. 11g'de DDL'nizi bekletebilirsiniz. Bunu şimdi yapıyorum. İyi çalışıyor.
Bob

3
11g'de ÖZEL MODDA KİLİT TABLOSU tablo_adı kullanmalısınız;
Kamil Roman

1
Bu, ORA-00054'ü toplu işlerden alıyorsanız gerçekten yararlıdır, ancak buraya inen çoğu insanın (OP ve ben dahil) biraz gelişme gösterdiğinden ve aynı masada ekler yaparak bir oturum açık bıraktığından şüpheleniyorum ' bırakıp yeniden yaratmaya çalışıyoruz. KILL SESSIONbu insanlar için doğru cevaptır.
Andrew Spencer

@Bob Hem 11g hem de eski yol için örnek kod iyi olurdu. Sözdizimi nedir set_ddl_timeoutve ne olmalı?
vapcguy

1
@vapcguy bu benim için 11g'de çalıştı: ALTER SYSTEM SET ddl_lock_timeout=20;bkz. dokümanlar
rshdev

13

Bu hata, kaynak meşgul olduğunda oluşur. Sorguda herhangi bir başvuru kısıtlaması olup olmadığını kontrol edin. Veya sorguda belirttiğiniz tablolar meşgul olabilir. Aşağıdaki sorgu sonuçlarında kesinlikle listelenecek başka bir iş ile meşgul olabilirler:

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

SID'yi bulun,

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

1
Herkesin bu görüşlere erişimi olmayacak. Anladım ORA-00942: table or view does not exist.
vapcguy

Bu gibi durumlarda, DB Yöneticileri bu bilgileri sağlamaktan sorumludur.
Arunchunaivendan

Her zaman değil. Kodun çözülmesi ve bunun üzerinde çalışılması gerekiyordu ve ne ben ne de hizmet hesabım bu haklara sahip olmayacak.
vapcguy

7

Bu, bir tabloyu değiştirmek için kullanılan oturumdan farklı bir oturumun DML (güncelleme / silme / ekleme) nedeniyle bir kilit tutması durumunda olur. Yeni bir sistem geliştiriyorsanız, sizin veya ekibinizdeki birisinin güncelleme bildirimini yayınlaması muhtemeldir ve oturumu çok fazla sonuç vermeden öldürebilirsiniz. Veya oturumun kimin açık olduğunu öğrendikten sonra o oturumdan taahhütte bulunabilirsiniz.

Bir SQL yönetici sistemine erişiminiz varsa, rahatsız edici oturumu bulmak için kullanın. Ve belki de öldürün.

V $ oturumu ve v $ kilidi ve diğerlerini kullanabilirsiniz, ancak Google'a bu oturumu nasıl bulacağınızı ve sonra nasıl öldüreceğinizi öneririm.

Bir üretim sisteminde, bu gerçekten bağlıdır. 10 g ve üzeri kehanet için

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

Ayrı bir oturumda ancak çok uzun sürmesi durumunda aşağıdakileri hazır bulundurun.

alter system kill session '....

Hangi sisteme sahip olduğunuza bağlıdır, eski sistemlerin her seferinde taahhütte bulunmama olasılığı daha yüksektir. Uzun süreli kilitler olabileceğinden bu bir problemdir. Böylece kilidiniz yeni kilitleri önler ve kimin ne zaman serbest bırakılacağını bilen bir kilit bekler. Bu yüzden başka bir ifadeye hazırsınız. Ya da benzer şeyleri otomatik olarak yapan PLSQL komut dosyalarını arayabilirsiniz.

11g sürümünde, bekleme süresini ayarlayan yeni bir ortam değişkeni vardır. Sanırım muhtemelen tarif ettiğim şeye benzer bir şey yapıyor. Kilitleme sorunlarının ortadan kalkmadığını unutmayın.

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

Son olarak, bu tür bir bakım yapmak için sistemde çok az kullanıcı olana kadar beklemek en iyisi olabilir.


alter system kill session '....Yönetim görünümlerine erişiminiz yoksa öldürülecek oturumu nasıl öğreneceksiniz ?
vapcguy

Bilmiyorum.
Arturo Hernandez

7

Benim durumumda, engelli olan kendi oturumlarımdan biri olduğundan emindim . Bu nedenle, aşağıdakileri yapmak güvenlidir:

  • Sorunlu oturumu şu şekilde buldum:

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

    Oturum etkin değildi , ama yine de bir şekilde kilidi tuttu. Durumunuzda başka bir WHERE koşulu kullanmanız gerekebileceğini unutmayın (örneğin, deneme USERNAMEveya MACHINEalanlar).

  • Oturumu kullanarak yukarıda IDve sonra SERIAL#edinilmiş:

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

@Thermz tarafından düzenlendi: Önceki açık oturum sorgularının hiçbiri işe yaramazsa bunu deneyin. Bu sorgu, oturumları öldürürken sözdizimi hatalarından kaçınmanıza yardımcı olabilir:

  • SELECT 'ALTER SYSTEM KILL SESSION '''||SID||','||SERIAL#||''' immediate;' FROM V$SESSION WHERE OSUSER='my_local_username_on_OS'

Önceki açık oturum sorgularının hiçbiri işe yaramazsa, bunu deneyin.
thermz

5

Sadece oturumu tutan süreci kontrol edin ve öldürün. Normale döndü.

SQL'in altında işleminizi bulacaksınız

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;

Öyleyse öldür

ALTER SYSTEM KILL SESSION 'sid,serial#'

VEYA

çevrimiçi bulduğum bazı örneklerin, örneğin 130,620, @ 1 'sistem öldürme oturumunu değiştirmesi için örnek kimliğine ihtiyacı olduğu görülüyor;



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

Sadece bir tablo oluştururken bu hatayı vurmayı başardım! Tabii ki henüz var olmayan bir tabloda herhangi bir çekişme sorunu yoktu. CREATE TABLEİfadesi bir içeriyordu CONSTRAINT fk_name FOREIGN KEYiyi nüfuslu tabloya başvuran maddesini. Yapmak zorundaydım:

  • FOREIGN KEY yan tümcesini CREATE TABLE deyiminden kaldırma
  • FK sütununda bir INDEX oluşturma
  • FK oluşturun

Ben de aynı problemi yaşadım. Ben ddl deyiminden fk tanımını kaldırdıktan sonra tablo oluşturmak başardı, ama ben bile sütunda dizin oluşturduktan sonra ekleyemiyorum.
vadipp

Çözebildim. İlk olarak, 'e bir novalidatemadde ekledim alter table add constraint. Bu bir şekilde çalışmasına izin verir, ancak kilitlenir. Sonra hangi oturumda kilitlendiğini öğrenmek için oturum kilitlerine baktım. Sonra o oturumu öldürdüm.
vadipp

3

Çalıştığım 2 komut dosyası olduğunda bu hatayla karşılaştım. Sahiptim:

  • Şema kullanıcı hesabı kullanılarak doğrudan bağlanan bir SQL * Plus oturumu (hesap # 1)
  • Farklı bir şema kullanıcı hesabı (hesap # 2) kullanılarak bağlanan, ancak ilk hesap olarak bir veritabanı bağlantısı üzerinden bağlanan başka bir SQL * Plus oturumu

Bir tablo bırakma, sonra hesap oluşturma olarak tablo oluşturma # 1. Hesap # 2'nin oturumunda bir tablo güncellemesi yaptım. Değişiklik yapmadı. Tablo bırakma / oluşturma komut dosyasını hesap 1 olarak yeniden çalıştırdı. Komutta hata var drop table x.

COMMIT;Hesap 2'nin SQL * Plus oturumunda çalıştırarak çözdüm .


Tablo bırakma izniniz yoksa ne yapacaksınız? Kötü cevap
Shakeer Hussain

1
Shakeer, bu sadece başıma geldiğimde ne yaptığımın bir örneğiydi - sorunun çözümü değil - bu benim en son satırımda - çalışan bir COMMIT;. Bir tabloyu bile bırakamıyorsanız, öncelikle bu konuya girmenizi sağlayacak hiçbir şeyi değiştirme izniniz yoktur.
vapcguy

-2

Ben de benzer bir sorunla karşı karşıyayım. Bu hatayı gidermek için hiçbir programcının yapması gerekmez. Kahin DBA ekibime haber verdim. Oturumu öldürüyorlar ve bir cazibe gibi çalıştılar.


1
Birisi hala bir şeyler yapmak zorunda. DBA ekibi ne yapacağını ve bir oturumu nasıl öldüreceğini bilmiyorsa ne olur? Kötü cevap.
vapcguy

1
DBA oturumu nasıl öldüreceğini bilmiyorsa o zaman işe yaramaz
Shakeer Hussain

Yanlış anlamamak için herkesin zaman zaman sözdiziminde tazelenmeye ihtiyacı vardır.
vapcguy

-5

Shashi'nin bağlantısıyla verilen çözüm en iyisidir ... dba veya başka biriyle iletişime geçmeye gerek yoktur

yedekleme yapmak

create table xxxx_backup as select * from xxxx;

tüm satırları sil

delete from xxxx;
commit;

yedeklemenizi ekleyin.

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

10
sil / kısalt değiştirilemez. çok sayıda silme işlemi gerçekleştirmenin büyük performans sonuçları vardır. Bu gerçekten kötü.
Bob

Bunun ortak bir örüntü olduğunu düşündüm.
Shawn Xue
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.