java.sql.SQLException: - ORA-01000: maksimum açık imleçler aşıldı


115

ORA-01000 SQL istisnası alıyorum. Onunla ilgili bazı sorularım var.

  1. Maksimum açık imleçler, JDBC bağlantılarının sayısıyla tam olarak mı ilişkili yoksa aynı zamanda tek bir bağlantı için oluşturduğumuz ifade ve sonuç kümesi nesneleriyle mi ilgili? (Bağlantı havuzunu kullanıyoruz)
  2. Veritabanındaki ifade / sonuç kümesi nesnelerinin sayısını yapılandırmanın bir yolu var mı (bağlantılar gibi)?
  3. Tek iş parçacıklı bir ortamda yöntem yerel ifadesi / resultset nesnesi yerine örnek değişken deyimi / sonuç kümesi nesnesi kullanılması tavsiye edilir mi?
  4. Bir döngü içinde hazırlanmış bir ifadenin yürütülmesi bu soruna neden olur mu? (Tabii ki sqlBatch kullanabilirdim) Not: pStmt döngü bittikten sonra kapanır.

    { //method try starts  
      String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
      pStmt = obj.getConnection().prepareStatement(sql);
      pStmt.setLong(1, subscriberID);
      for (String language : additionalLangs) {
        pStmt.setInt(2, Integer.parseInt(language));
        pStmt.execute();
      }
    } //method/try ends
    
    { //finally starts
       pStmt.close()
    } //finally ends 
  5. Conn.createStatement () ve conn.prepareStatement (sql), tek bir bağlantı nesnesinde birden çok kez çağrılırsa ne olur?

Düzenleme1: 6. Zayıf / Yumuşak referans ifadesi nesnesinin kullanılması sızıntıyı önlemeye yardımcı olur mu?

Edit2: 1. Projemde eksik olan tüm "statement.close ()" ları bulabileceğim bir yol var mı? Hafıza sızıntısı olmadığını anlıyorum. Ancak çöp toplama için uygun bir ifade referansı (close () gerçekleştirilmezse) bulmam gerekiyor mu? Herhangi bir alet mevcut mu? Yoksa manuel olarak mı analiz etmem gerekiyor?

Lütfen anlamama yardım et.

Çözüm

Oracle DB'de -VELU kullanıcı adı için açık imleci bulmak için

ORACLE makinesine gidin ve sqlplus'ı sysdba olarak başlatın.

[oracle@db01 ~]$ sqlplus / as sysdba 

O zaman koş

SELECT   A.VALUE,
    S.USERNAME,
    S.SID,
    S.SERIAL#
  FROM V$SESSTAT A,
    V$STATNAME B,
    V$SESSION S
  WHERE A.STATISTIC# = B.STATISTIC#
    AND S.SID        = A.SID
    AND B.NAME       = 'opened cursors current'
    AND USERNAME     = 'VELU';

Mümkünse , çözümümü daha iyi anlamak için lütfen cevabımı okuyun


Kodunuzun tamamını gönderebilir misiniz? Açılan parantezleri nerede kapattığınızı görmek ilginç olurdufor (String language : additionalLangs) {
Jåcob

@ Kanagavelu Sugumar: Neden SO'da 5 farklı soru sormuyorsunuz?
Jayan

1
İşte çok yararlı bulduğum bir yanıt: stackoverflow.com/a/4507507/501113
chaotic3quilibrium

Lütfen cevabın işe
Manu

Oracle'da açık imleçleri izlemek için, görünüme de göz atmak isteyebilirsiniz SYS.V$OPEN_CURSOR. Bu size sadece SID'yi değil, aynı zamanda SQL metnini de verecektir.
Bass

Yanıtlar:


291

ORA-01000, maksimum açık imleç hatası, Oracle veritabanı geliştirmede oldukça yaygın bir hatadır. Java bağlamında, uygulama bir veritabanı örneğinde yapılandırılmış imleçlerden daha fazla ResultSets açmaya çalıştığında gerçekleşir.

Yaygın nedenler şunlardır:

  1. Yapılandırma hatası

    • Uygulamanızda veritabanını sorgulayan, DB'deki imleçlerden daha fazla iş parçacığı var. Veritabanındaki imleç sayısından daha büyük bir bağlantınız ve iş parçacığı havuzunuzun olduğu durumlardan biri.
    • Aynı DB örneğine bağlı birçok geliştiriciniz veya uygulamanız var (muhtemelen birçok şema içerecektir) ve birlikte çok fazla bağlantı kullanıyorsunuz.
    • Çözüm:

  2. İmleç sızıntısı

    • Uygulamalar, ResultSets'i (JDBC'de) veya imleçleri (veritabanındaki saklı yordamlarda) kapatmıyor
    • Çözüm : İmleç sızıntıları hatalardır; DB'deki imleç sayısının artırılması, kaçınılmaz arızayı basitçe geciktirir. Sızıntılar, statik kod analizi , JDBC veya uygulama düzeyinde günlük kaydı ve veritabanı izleme kullanılarak bulunabilir .

Arka fon

Bu bölüm, imleçlerin arkasındaki bazı teorileri ve JDBC'nin nasıl kullanılması gerektiğini açıklamaktadır. Arka planı bilmeniz gerekmiyorsa, bunu atlayabilir ve doğrudan "Sızıntıları Ortadan Kaldırma" bölümüne gidebilirsiniz.

İmleç nedir?

İmleç, veritabanında bir sorgunun durumunu, özellikle de okuyucunun ResultSet'te bulunduğu konumu tutan bir kaynaktır. Her SELECT deyiminin bir imleci vardır ve PL / SQL saklı yordamları, ihtiyaç duydukları kadar çok imleci açabilir ve kullanabilir. Orafaq'ta imleçler hakkında daha fazla bilgi edinebilirsiniz .

Bir veritabanı örneği tipik olarak , her biri birden çok oturuma sahip birçok farklı kullanıcı olan birkaç farklı şemaya hizmet eder . Bunu yapmak için, tüm şemalar, kullanıcılar ve oturumlar için kullanılabilir sabit sayıda imleci vardır. Tüm imleçler açık olduğunda (kullanımda) ve yeni bir imleç gerektiren istek geldiğinde, istek ORA-010000 hatasıyla başarısız olur.

İmleç sayısını bulma ve ayarlama

Numara normalde kurulum sırasında DBA tarafından yapılandırılır. Şu anda kullanımda olan imleç sayısı, maksimum sayı ve konfigürasyona Oracle SQL Developer'daki Yönetici işlevlerinden erişilebilir . SQL'den şu şekilde ayarlanabilir:

ALTER SYSTEM SET OPEN_CURSORS=1337 SID='*' SCOPE=BOTH;

JVM'deki JDBC'yi DB'deki imleçlerle ilişkilendirme

Aşağıdaki JDBC nesneleri, aşağıdaki veritabanı kavramlarına sıkı sıkıya bağlıdır:

  • JDBC Bağlantısı , bir veritabanı oturumunun müşteri temsilidir ve veritabanı işlemlerini sağlar . Bir bağlantı herhangi bir anda yalnızca tek bir işlem açık olabilir (ancak işlemler iç içe yerleştirilebilir)
  • JDBC ResultSet , veritabanında tek bir imleç tarafından desteklenir . ResultSet'te close () çağrıldığında imleç serbest bırakılır.
  • JDBC CallableStatement , genellikle PL / SQL'de yazılan veritabanında bir saklı yordamı çağırır . Depolanan yordam, sıfır veya daha fazla imleç oluşturabilir ve bir imleci JDBC Sonuç Kümesi olarak döndürebilir.

JDBC iş parçacığı güvenlidir: Çeşitli JDBC nesnelerini iş parçacıkları arasında geçirmek oldukça uygundur.

Örneğin, bağlantıyı tek bir iş parçacığında oluşturabilirsiniz; başka bir iş parçacığı bu bağlantıyı bir PreparedStatement oluşturmak için kullanabilir ve üçüncü bir iş parçacığı sonuç kümesini işleyebilir. Tek önemli kısıtlama, herhangi bir zamanda tek bir PreparedStatement üzerinde birden fazla ResultSet'in açık olmamasıdır. Bkz bağlantı başına mu Oracle DB desteği çoklu (paralel) işlemleri?

Bir Bağlantıda bir veritabanı kesinleştirme gerçekleştiğini ve bu nedenle bu bağlantıdaki tüm DML'lerin (INSERT, UPDATE ve DELETE'ler) birlikte işleme alınacağını unutmayın. Bu nedenle, aynı anda birden fazla işlemi desteklemek istiyorsanız, her bir eşzamanlı İşlem için en az bir Bağlantınız olmalıdır.

JDBC nesnelerini kapatma

Bir ResultSet çalıştırmanın tipik bir örneği:

Statement stmt = conn.createStatement();
try {
    ResultSet rs = stmt.executeQuery( "SELECT FULL_NAME FROM EMP" );
    try {
        while ( rs.next() ) {
            System.out.println( "Name: " + rs.getString("FULL_NAME") );
        }
    } finally {
        try { rs.close(); } catch (Exception ignore) { }
    }
} finally {
    try { stmt.close(); } catch (Exception ignore) { }
}

Nihayet cümlesinin close () tarafından oluşturulan istisnaları nasıl yok saydığına dikkat edin:

  • ResultSet'i try {} catch {} olmadan kapatırsanız, başarısız olabilir ve İfadenin kapanmasını engelleyebilir.
  • Denemenin gövdesinde ortaya çıkan herhangi bir istisnanın, arayan kişiye yayılmasına izin vermek istiyoruz. Örneğin, İfadeler oluşturmak ve yürütmek gibi bir döngünüz varsa, döngü içindeki her bir Deyimi kapatmayı unutmayın.

Java 7'de Oracle, Java 6 standart metninin çoğunu güzel sözdizimsel şekerle değiştiren AutoCloseable arayüzünü tanıttı .

JDBC nesnelerini tutma

JDBC nesneleri, yerel değişkenlerde, nesne örneğinde ve sınıf üyelerinde güvenli bir şekilde tutulabilir. Aşağıdakileri yapmak genellikle daha iyi bir uygulamadır:

  • Connections ve PreparedStatements gibi daha uzun bir süre boyunca birden çok kez yeniden kullanılan JDBC nesnelerini tutmak için nesne örneğini veya sınıf üyelerini kullanın
  • ResultSets için yerel değişkenler kullanın, çünkü bunlar elde edilir, döngü yapılır ve sonra tipik olarak tek bir işlev kapsamında kapatılır.

Bununla birlikte, bir istisna vardır: EJB'ler veya bir Servlet / JSP konteyneri kullanıyorsanız, katı bir iş parçacığı modeli izlemeniz gerekir:

  • Yalnızca Uygulama Sunucusu iş parçacıkları oluşturur (bununla gelen istekleri ele alır)
  • Yalnızca Uygulama Sunucusu bağlantılar oluşturur (bağlantı havuzundan elde ettiğiniz)
  • Aramalar arasında değerleri (durum) kaydederken çok dikkatli olmalısınız. Değerleri asla kendi önbelleklerinizde veya statik üyelerinizde saklamayın - bu, kümeler ve diğer garip koşullar için güvenli değildir ve Uygulama Sunucusu verilerinize korkunç şeyler yapabilir. Bunun yerine durum bilgisi olan fasulye veya bir veritabanı kullanın.
  • Özellikle, farklı uzaktan çağrılar üzerinden JDBC nesnelerini (Connections, ResultSets, PreparedStatements, vb.) Asla tutmayın - bırakın Uygulama Sunucusu bunu yönetsin. Uygulama Sunucusu yalnızca bir bağlantı havuzu sağlamakla kalmaz, aynı zamanda PreparedStatements'ınızı da önbelleğe alır.

Sızıntıları ortadan kaldırmak

JDBC sızıntılarını tespit etmeye ve ortadan kaldırmaya yardımcı olacak bir dizi süreç ve araç vardır:

  1. Geliştirme sırasında - böcekleri erken yakalamak, açık ara en iyi yaklaşımdır:

    1. Geliştirme uygulamaları: İyi geliştirme uygulamaları, geliştiricinin masasından ayrılmadan önce yazılımınızdaki hataların sayısını azaltmalıdır. Belirli uygulamalar şunları içerir:

      1. Yeterli deneyime sahip olmayanları eğitmek için eşli programlama
      2. Birçok göz birden daha iyi olduğu için kod incelemeleri
      3. Birim testi ; bu, kod tabanınızın herhangi birini veya tamamını bir test aracından uygulayabileceğiniz anlamına gelir; bu da sızıntıları yeniden üretmeyi önemsiz hale getirir.
      4. Kendi kütüphanenizi oluşturmak yerine bağlantı havuzu oluşturmak için mevcut kitaplıkları kullanın
    2. Statik Kod Analizi: Statik kod analizi yapmak için mükemmel Findbug'lar gibi bir araç kullanın . Bu, close () öğesinin doğru şekilde işlenmediği birçok yeri alır. Findbugs, Eclipse için bir eklentiye sahiptir, ancak aynı zamanda tek seferlik kullanım için bağımsız çalışır, Jenkins CI ve diğer oluşturma araçlarına entegrasyonları vardır

  2. İşlem esnasında:

    1. Tutulabilirlik ve taahhüt

      1. ResultSet tutulabilirliği ResultSet.CLOSE_CURSORS_OVER_COMMIT ise, Connection.commit () yöntemi çağrıldığında ResultSet kapatılır. Bu, Connection.setHoldability () kullanılarak veya aşırı yüklenmiş Connection.createStatement () yöntemi kullanılarak ayarlanabilir.
    2. Çalışma zamanında günlük kaydı.

      1. Kodunuza iyi günlük ifadeleri ekleyin. Müşteri, destek personeli ve ekip arkadaşlarının eğitim almadan anlayabilmesi için bunlar açık ve anlaşılır olmalıdır. Kısa olmalılar ve işlem mantığını izleyebilmeniz için anahtar değişkenlerin ve özniteliklerin durum / dahili değerlerini yazdırmayı içermelidirler. İyi günlük kaydı, uygulamalarda, özellikle konuşlandırılmış uygulamalarda hata ayıklama için çok önemlidir.
      2. Projenize bir hata ayıklama JDBC sürücüsü ekleyebilirsiniz (hata ayıklama için - gerçekten dağıtmayın). Bir örnek (kullanmadım) log4jdbc'dir . Daha sonra, hangi yürütmelerin karşılık gelen kapanışına sahip olmadığını görmek için bu dosya üzerinde bazı basit analizler yapmanız gerekir. Açık ve kapalı sayıları saymak, potansiyel bir sorun olup olmadığını vurgulamalıdır

        1. Veritabanını izleme. SQL Developer 'Monitor SQL' işlevi veya Quest's TOAD gibi araçları kullanarak çalışan uygulamanızı izleyin . Bu makalede izleme anlatılmaktadır . İzleme sırasında, açık imleçleri (örneğin tablo v $ sesstat'tan) sorgulayıp SQL'lerini gözden geçirirsiniz. İmleçlerin sayısı artıyorsa ve (en önemlisi) tek bir özdeş SQL ifadesi tarafından yönetiliyorsa, o SQL'de bir sızıntınız olduğunu bilirsiniz. Kodunuzu arayın ve inceleyin.

Diğer düşünceler

Bağlantıları kapatmak için WeakReferences'ı kullanabilir misiniz?

Zayıf ve yumuşak referanslar, bir nesneye, JVM'nin uygun gördüğü herhangi bir zamanda referansı çöp toplamasına izin verecek şekilde referans vermenize izin verme yollarıdır (bu nesneye yönelik güçlü referans zincirleri olmadığı varsayılarak).

Yapıcıda bir ReferenceQueue'yu yumuşak veya zayıf Reference'a iletirseniz, nesne oluştuğunda GC'lendiğinde (eğer ortaya çıkarsa) nesne ReferenceQueue'ya yerleştirilir. Bu yaklaşımla, nesnenin sonlandırılmasıyla etkileşime girebilir ve nesneyi o anda kapatabilir veya sonlandırabilirsiniz.

Hayali referanslar biraz daha tuhaftır; amaçları yalnızca sonlandırmayı kontrol etmektir, ancak orijinal nesneye asla bir referans alamazsınız, bu nedenle üzerinde close () yöntemini çağırmak zor olacaktır.

Ancak, GC çalıştırıldığında kontrol etmeye çalışmak nadiren iyi bir fikirdir (Weak, Soft ve PhantomReferences , nesnenin GC için kuyruğa alındıktan sonra size haber verir ). Aslında, JVM'deki bellek miktarı büyükse (örneğin, -Xmx2000m) , nesneyi asla GC yapamazsınız ve yine de ORA-01000 deneyimini yaşarsınız. JVM belleği, programınızın gereksinimlerine göre küçükse, ResultSet ve PreparedStatement nesnelerinin oluşturulduktan hemen sonra (siz bunlardan okuyabilmeniz için) GC'ye tabi tutulduğunu görebilirsiniz, bu da muhtemelen programınızda başarısız olur.

TL; DR: Zayıf referans mekanizması, Statement ve ResultSet nesnelerini yönetmek ve kapatmak için iyi bir yol değildir.


3
Bir döngüde ifadeler oluşturursanız, döngüde kapalı olduğundan emin olun, aksi takdirde yalnızca son ifadeyi kapatırsınız.
basiljames

Teşekkürler, basiljames. Yaptığınız noktayı eklemek için yanıtı düzenledim.
Andrew Alcock

@ Andrew Alcock Çok teşekkürler! Andrew. Lütfen 6. maddeye de cevap verir misiniz?
Kanagavelu Sugumar

@AndrewAlcock Lütfen .. lütfen .. lütfen .. 7. soruma da cevap ver. Projemizden bu yana yük testi sırasında ORA-01000 ile çok sık karşılaşıyoruz. Girdileriniz benim için daha değerli. Şimdiden bir ton teşekkürler !!
Kanagavelu Sugumar

RE: 7 - grep gibi bir araç kullanarak yakınlık aramayı deneyebilirsiniz. Bir SQL'i tanıdığınızda (seçme, ekleme, güncelleme, silme), ifadenin yanındaki close () kelimesinin yakınlığına bakın. Yakınlık beklenenden daha uzaksa, bu, nerede eksik olduğunu araştırmanın bir yolu olabilir. lightboxtechnologies.com/2012/07/27/…
Paz

28

Birkaç anlayış ekliyorum.

  1. İmleç yalnızca bir ifade nesnesi hakkındadır; Ne resultSet ne de bağlantı nesnesidir.
  2. Ama yine de bazı oracle belleğini boşaltmak için sonuç kümesini kapatmalıyız. Yine de CURSORS için sayılmayacak sonuç kümesini kapatmazsanız.
  3. Kapanış İfadesi nesnesi de sonuç kümesi nesnesini otomatik olarak kapatır.
  4. İmleç, tüm SELECT / INSERT / UPDATE / DELETE deyimi için oluşturulacaktır.
  5. Her ORACLE DB örneği, oracle SID kullanılarak tanımlanabilir; benzer şekilde ORACLE DB, bağlantı SID'sini kullanarak her bir bağlantıyı tanımlayabilir. Her iki SID farklıdır.
  6. Yani ORACLE oturumu bir jdbc (tcp) bağlantısından başka bir şey değildir; bu tek bir SID'den başka bir şey değildir.
  7. Maksimum imleci 500 olarak belirlersek, bu sadece bir JDBC oturumu / bağlantısı / SID içindir.
  8. Böylece, ilgili imleç (ifadeler) ile birçok JDBC bağlantımız olabilir.
  9. JVM sonlandırıldığında, tüm bağlantılar / imleçler kapatılır VEYA JDBCConnection kapanır, bu bağlantıya göre CURSORS kapatılır.

Sysdba olarak oturum açın.

Putty'de (Oracle girişi):

  [oracle@db01 ~]$ sqlplus / as sysdba

SqlPlus'ta:

Kullanıcı adı: sys as sysdba

Session_cached_cursors değerini, kapalı imleçlere sahip olmayacak şekilde 0 olarak ayarlayın.

 alter session set session_cached_cursors=0
 select * from V$PARAMETER where name='session_cached_cursors'

DB'de bağlantı başına mevcut OPEN_CURSORS değer kümesini seçin

 SELECT max(a.value) as highest_open_cur, p.value as max_open_cur FROM v$sesstat a, v$statname b, v$parameter p WHERE a.statistic# = b.statistic# AND b.name = 'opened cursors current' AND p.name= 'open_cursors'  GROUP BY p.value;

Aşağıda, açık imleç değerlerine sahip SID / bağlantı listesini bulma sorgusu bulunmaktadır.

 SELECT a.value, s.username, s.sid, s.serial#
 FROM v$sesstat a, v$statname b, v$session s
 WHERE a.statistic# = b.statistic#  AND s.sid=a.sid 
 AND b.name = 'opened cursors current' AND username = 'SCHEMA_NAME_IN_CAPS'

Açık imleçlerdeki sql'leri tanımlamak için aşağıdaki sorguyu kullanın

 SELECT oc.sql_text, s.sid 
 FROM v$open_cursor oc, v$session s
 WHERE OC.sid = S.sid
 AND s.sid=1604
 AND OC.USER_NAME ='SCHEMA_NAME_IN_CAPS'

Şimdi Kodda hata ayıklayın ve Keyfini Çıkarın !!! :)


1
İşte iyi çalışan başka bir sorgu: stackoverflow.com/a/2560415/32453
rogerdpack

4

Kodunuzu şu şekilde düzeltin:

try
{ //method try starts  
  String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
  pStmt = obj.getConnection().prepareStatement(sql);
  pStmt.setLong(1, subscriberID);
  for (String language : additionalLangs) {
    pStmt.setInt(2, Integer.parseInt(language));
    pStmt.execute();
  }
} //method/try ends
finally
{ //finally starts
   pStmt.close()
} 

PStatement'larınızı, bağlantılarınızı ve sonuçlarınızı gerçekten kapattığınızdan emin misiniz?

Açık nesneleri analiz etmek için, kodu durumunuzun, bağlantınızın ve sonuç nesnelerinizin etrafına saran bir temsilci modeli uygulayabilirsiniz. Böylece, bir nesnenin başarıyla kapatılıp kapatılmayacağını göreceksiniz.

Şunun için bir örnek: pStmt = obj. getConnection () .prepareStatement (sql);

    class obj{ 

    public Connection getConnection(){
    return new ConnectionDelegator(...here create your connection object and put it into ...);

    } 
}


class ConnectionDelegator implements Connection{
    Connection delegates;

    public ConnectionDelegator(Connection con){
       this.delegates = con;
    }

    public Statement prepareStatement(String sql){
        return delegates.prepareStatement(sql);
    }

    public void close(){
        try{
           delegates.close();
        }finally{
           log.debug(delegates.toString() + " was closed");
        }
    }
}

3

Uygulamanız, uygulama sunucusu olarak Oracle WebLogic üzerinde çalışan bir Java EE uygulamasıysa, bu sorunun olası nedeni İfade Önbelleği Boyutu'dur. WebLogic'teki ayarıdır.

Belirli bir veri kaynağı için İfade Önbelleği Boyutu ayarı Oracle veritabanı maksimum açık imleç sayısı ayarına eşit veya bundan büyükse, açık imleçlerin tümü WebLogic tarafından açık tutulan önbelleğe alınmış SQL deyimleri tarafından tüketilebilir ve ORA-01000 hatası.

Bunu ele almak için, Oracle veritabanına işaret eden her WebLogic veri kaynağı için İfade Önbelleği Boyutu ayarını, veritabanındaki maksimum imleç sayısı ayarından önemli ölçüde daha az olacak şekilde azaltın.

WebLogic 10 Yönetici Konsolunda, her veri kaynağı için İfade Önbelleği Boyutu ayarı Hizmetler (sol gezinme bölmesi)> Veri Kaynakları> (ayrı veri kaynağı)> Bağlantı Havuzu sekmesinde bulunabilir.


1
Hazırda bekletme de bir Bildirim önbelleğine sahiptir. Ayrıca bkz. Developer.jboss.org/wiki/…
Pino

3

Ben de bu sorunla karşılaştım, aşağıdaki istisna geliyordu

java.sql.SQLException: - ORA-01000: maximum open cursors exceeded

Dao katmanı için Spring JDBC ile Spring Framework kullanıyordum .

Uygulamam bir şekilde imleçleri sızdırıyordu ve birkaç dakika sonra bana bu istisnayı veriyordu.

Kapsamlı hata ayıklama ve analizlerin çoğunda sonra sorun olmadığını buldular , İlköğretim anahtar ve benzersiz Kısıtlamaları Endeks birinde Tablo kullanılıyor Query i infaz edildi.

Uygulamam, yanlışlıkla Dizine eklenen Sütunları güncellemeye çalışıyordu . Dolayısıyla, uygulamam dizine eklenen sütunlarda güncelleme sorgusuna her vurduğunda, veritabanı güncellenen değerlere göre yeniden dizin oluşturmaya çalışıyordu. İmleçleri sızdırıyordu .

Sorguda arama yapmak için kullanılan sütunlar üzerinde Doğru İndeksleme yaparak ve gereken yerlerde uygun kısıtlamaları uygulayarak sorunu çözebildim.


2

Bugün aynı problemle (ORA-01000) karşılaştım. Bir Oracle DB'de bir SELECT ifadesini birçok kez yürütmek için (her seferinde bir parametre değiştirirken) ve sonunda {}, her zamanki gibi Resultset, PreparedStatement ve Connection'ı kapatmak için kodum vardı. . Ancak belirli bir döngü miktarına (1000) ulaşır ulaşmaz çok fazla açık imleçle ilgili Oracle hatası aldım.

Andrew Alcock'un yukarıdaki gönderisine dayanarak, içeride döngü , verileri aldıktan sonra ve tekrar döngüye girmeden önce her kümesini ve her bir ifadeyi kapattım ve bu da sorunu çözdü.

Ek olarak, aynı sorun başka bir Ekleme İfadeleri döngüsünde, başka bir Oracle DB'de (ORA-01000), bu kez 300 ifadeden sonra ortaya çıktı. Yine aynı şekilde çözüldü, yani PreparedStatement veya ResultSet veya her ikisi de kapanana kadar açık imleç olarak sayılır.


Bu doğru görünmüyor. ResultSets'i kapatmaktan sorumlu olduğu bahar belgeleri ( docs.spring.io/spring/docs/current/spring-framework-reference/… ).
Ryan

sadece açıklama için, bu örneklerde Spring kullanmıyordum.
Kinnison84

1

Autocommit = true ayarladınız mı? Bunu denemiyorsanız:

{ //method try starts  
    String sql = "INSERT into TblName (col1, col2) VALUES(?, ?)";
    Connection conn = obj.getConnection()
    pStmt = conn.prepareStatement(sql);

    for (String language : additionalLangs) {
        pStmt.setLong(1, subscriberID);
        pStmt.setInt(2, Integer.parseInt(language));
        pStmt.execute();
        conn.commit();
    }
} //method/try ends { 
    //finally starts
    pStmt.close()
} //finally ends 

Lütfen diğer soruları da cevaplayabilir misiniz?
Kanagavelu Sugumar

2
Autocommit bağlantıları kapatmaz - yalnızca her ifadeyi çalıştırdıktan hemen sonra otomatik olarak işler. Autocommit kullanıyorsanız, veritabanının en önemli özelliklerinden biri olan işlemlerden değer elde edemezsiniz. Bunun yerine bir NoSQL DB kullanmayı düşünebilirsiniz.
Andrew Alcock

1

açılan sql bulmak için sorgu.

SELECT s.machine, oc.user_name, oc.sql_text, count(1) 
FROM v$open_cursor oc, v$session s
WHERE oc.sid = s.sid
and S.USERNAME='XXXX'
GROUP BY user_name, sql_text, machine
HAVING COUNT(1) > 2
ORDER BY count(1) DESC

1

Bu sorun esas olarak bağlantı havuzunu kullandığınızda ortaya çıkar, çünkü bağlantıyı kapattığınızda bu bağlantı bağlantı havuzuna geri döner ve bu bağlantıyla ilişkili tüm imleç veritabanına bağlantı hala açık olduğundan hiçbir zaman kapanmaz. Bu nedenle bir alternatif, havuzdaki bağlantıların boşta kalma süresini azaltmaktır, bu nedenle bağlantı 10 saniye boyunca bağlantıda boşta kaldığında, veritabanına bağlantı kapatılır ve havuza yerleştirmek için yeni bağlantı oluşturulur.



0

Bizim durumumuzda, Hibernate kullanıyorduk ve aynı Hibernate eşlenmiş varlığa referans veren birçok değişkenimiz vardı. Bu referansları bir döngü içinde oluşturuyor ve kaydediyorduk. Her referans bir imleci açtı ve onu açık tuttu.

Bunu , kodumuzu çalıştırırken açık imleçlerin sayısını kontrol etmek için bir sorgu kullanarak , bir hata ayıklayıcıyla adım adım ilerleyerek ve şeyleri seçerek yorum yaparak keşfettik .

Her yeni referansın neden başka bir imleci açtığına gelince - söz konusu varlık, kendisiyle eşlenmiş diğer varlıkların koleksiyonlarına sahipti ve bunun onunla bir ilgisi olduğunu düşünüyorum (belki sadece bununla değil, getirme modunu ve önbellek ayarları). Hazırda bekletme, kapanamama konusunda hatalar yaşadı açık imleçleri , ancak bunlar sonraki sürümlerde düzeltilmiş gibi görünüyor.

Zaten aynı varlığa çok fazla yinelenen referansa ihtiyacımız olmadığından, çözüm, tüm bu gereksiz referansları oluşturmayı ve tutmayı bırakmaktı. Bunu bir kez yaptık, sorun uzaktayken.


0

Bu sorunu WildFly ve Tomcat'teki veri kaynağımda Oracle 10g'ye bağlanırken yaşadım.

Belirli koşullar altında, ifade.close () çağrıldığında bile ifadenin kapatılmadığını buldum. Sorun, kullandığımız Oracle Sürücüsüydü: ojdbc7.jar. Bu sürücü Oracle 12c ve 11g için tasarlanmıştır ve Oracle 10g ile kullanıldığında bazı sorunlar yaşanmaktadır, bu yüzden ojdbc5.jar'a geçiyorum ve şimdi her şey yolunda gidiyor.


0

Aynı sorunla karşılaştım çünkü 1000'den fazla yineleme için db'yi sorguluyordum. Try ve nihayet kodumda kullandım. Ama yine de hata alıyordu.

Bunu çözmek için oracle db'ye giriş yaptım ve aşağıdaki sorguyu çalıştırdım:

ALTER SYSTEM SET open_cursors = 8000 KAPSAM = HER İKİSİ;

Ve bu benim sorunumu hemen çözdü.


Bu, bazı semptomları kurtardı ama aslında sorunu çözmedi. Kodunuzu, bittikten sonra imleçleri kapatacak şekilde düzeltmeniz gerekir.
APC
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.