java.sql.SQLException: - ORA-01000: अधिकतम खुले कर्सर पार हो गए


115

मुझे ORA-01000 SQL अपवाद मिल रहा है। इसलिए मेरे पास इससे संबंधित कुछ प्रश्न हैं।

  1. क्या अधिकतम खुले कर्सर वास्तव में जेडीबीसी कनेक्शनों की संख्या से संबंधित हैं, या क्या वे एकल कनेक्शन के लिए बनाए गए कथन और परिणामी वस्तुओं से भी संबंधित हैं? (हम कनेक्शन के पूल का उपयोग कर रहे हैं)
  2. क्या डेटाबेस में स्टेटमेंट / परिणामी वस्तुओं की संख्या (जैसे कनेक्शन) को कॉन्फ़िगर करने का कोई तरीका है?
  3. क्या एकल थ्रेडेड वातावरण में विधि स्थानीय कथन / परिणामी वस्तु के बजाय उदाहरण चर कथन / परिणाम वस्तु का उपयोग करना उचित है?
  4. क्या किसी तैयार किए गए कथन को एक लूप में निष्पादित करना इस समस्या का कारण बनता है? (बेशक, मैं sqlBatch इस्तेमाल किया जा सकता है) ध्यान दें: पाश खत्म हो जाने के बाद pStmt बंद हो जाता है।

    { //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. क्या होगा यदि con.createStatement () और con.prepareStatement (sql) को किसी भी कनेक्शन ऑब्जेक्ट पर कई बार कहा जाए?

Edit1: 6. कमजोर / नरम संदर्भ स्टेटमेंट ऑब्जेक्ट के उपयोग से रिसाव को रोकने में मदद मिलेगी?

Edit2: 1. क्या कोई रास्ता है, मैं अपनी परियोजना में सभी लापता "स्टेटमेंट (।) ()" पा सकता हूं? मैं समझता हूं कि यह मेमोरी लीक नहीं है। लेकिन मुझे कचरा संग्रह के लिए एक बयान संदर्भ (जहां करीब () प्रदर्शन नहीं किया गया है) खोजने की आवश्यकता है? कोई उपकरण उपलब्ध है? या क्या मुझे इसे मैन्युअल रूप से विश्लेषण करना है?

कृपया इसे समझने में मेरी मदद करें।

उपाय

उपयोगकर्ता नाम के लिए Oracle DB में खोला कर्सर खोजने के लिए -UU

ORACLE मशीन पर जाएं और sqlplus को sysdba के रूप में शुरू करें।

[oracle@db01 ~]$ sqlplus / as sysdba 

फिर भागो

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

यदि संभव हो तो कृपया मेरे समाधान की अधिक समझ के लिए मेरा उत्तर पढ़ें


क्या आप अपना पूरा कोड पोस्ट कर सकते हैं? यह देखना दिलचस्प होगा कि आप खुलने वाले ब्रेसिज़ को कहाँ से बंद कर रहे हैंfor (String language : additionalLangs) {
Jåcob

@ कानागावेलु सुगुमार: एसओ में 5 अलग-अलग सवाल क्यों नहीं पूछते?
जयन सिप

1
यहाँ एक प्रतिक्रिया मुझे बहुत उपयोगी
लगी

कृपया देखें कि क्या जवाब है उपयोगी: stackoverflow.com/questions/34716456/...
मनु

ओरेकल में खुले कर्सर को ट्रैक करने के लिए, आप भी SYS.V$OPEN_CURSORदृश्य पर एक नज़र रखना चाह सकते हैं । यह आपको न केवल SID, बल्कि SQL टेक्स्ट भी देगा।
बास

जवाबों:


290

ओआरए -01000, अधिकतम-खुले-कर्सर त्रुटि, ओरेकल डेटाबेस विकास में एक अत्यंत सामान्य त्रुटि है। जावा के संदर्भ में, यह तब होता है जब अनुप्रयोग डेटाबेस परिणाम पर कॉन्फ़िगर किए गए कर्सर की तुलना में अधिक परिणाम खोलने का प्रयास करता है।

सामान्य कारण हैं:

  1. कॉन्फ़िगरेशन गलती

    • आपके पास डीबी पर कर्सर की तुलना में डेटाबेस को क्वेरी करते हुए आपके आवेदन में अधिक धागे हैं। एक मामला यह है कि आपके पास डेटाबेस पर कर्सर की संख्या से बड़ा एक कनेक्शन और थ्रेड पूल है।
    • आपके पास एक ही DB उदाहरण से जुड़े कई डेवलपर्स या एप्लिकेशन हैं (जिसमें संभवतः कई स्कीमा शामिल होंगे) और साथ में आप बहुत सारे कनेक्शन का उपयोग कर रहे हैं।
    • उपाय:

  2. कर्सर लीक

    • अनुप्रयोग ResultSets (JDBC में) या कर्सर को बंद नहीं कर रहे हैं (डेटाबेस में संग्रहीत कार्यविधियों में)
    • समाधान : कर्सर लीक कीड़े हैं; DB पर अभिशापों की संख्या बढ़ने से बस अपरिहार्य विफलता होती है। लीक को स्थिर कोड विश्लेषण , जेडीबीसी या एप्लिकेशन-स्तर लॉगिंग और डेटाबेस मॉनिटरिंग का उपयोग करके पाया जा सकता है ।

पृष्ठभूमि

इस खंड में कर्सर के पीछे कुछ सिद्धांत का वर्णन है और JDBC का उपयोग कैसे किया जाना चाहिए। यदि आपको पृष्ठभूमि जानने की आवश्यकता नहीं है, तो आप इसे छोड़ सकते हैं और सीधे 'एलिमिनेटिंग लीक्स' पर जा सकते हैं।

एक कर्सर क्या है?

एक कर्सर डेटाबेस पर एक संसाधन है जो एक क्वेरी की स्थिति रखता है, विशेष रूप से उस स्थिति में जहां एक पाठक ResultSet में है। प्रत्येक सेलेक्ट स्टेटमेंट में एक कर्सर होता है, और PL / SQL स्टोर की गई प्रक्रिया को खोल सकते हैं और जितने की आवश्यकता होती है उतने कर्सर का उपयोग कर सकते हैं। आप Orafaq पर कर्सर के बारे में अधिक जानकारी प्राप्त कर सकते हैं ।

एक डेटाबेस उदाहरण आम तौर पर कई सत्रों के साथ कई अलग- अलग स्कीमा , कई अलग-अलग उपयोगकर्ता प्रदान करता है । ऐसा करने के लिए, इसमें सभी स्कीमा, उपयोगकर्ताओं और सत्रों के लिए निश्चित संख्या में कर्सर उपलब्ध हैं। जब सभी कर्सर खुले होते हैं (उपयोग में) और अनुरोध आता है जिसमें एक नए कर्सर की आवश्यकता होती है, तो ORA-010000 त्रुटि के साथ अनुरोध विफल हो जाता है।

शाप देने वालों की संख्या का पता लगाना और लगाना

स्थापना पर डीबीए द्वारा संख्या को सामान्य रूप से कॉन्फ़िगर किया गया है। वर्तमान में उपयोग किए जाने वाले कर्सर की संख्या, अधिकतम संख्या और कॉन्फ़िगरेशन को Oracle SQL डेवलपर में व्यवस्थापक कार्यों में एक्सेस किया जा सकता है । SQL से इसे इसके साथ सेट किया जा सकता है:

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

JVM में JDBC का संबंध DB पर श्रोताओं से है

नीचे दिए गए JDBC ऑब्जेक्ट्स को निम्नलिखित डेटाबेस अवधारणाओं के साथ कसकर जोड़ा गया है:

  • JDBC कनेक्शन एक डेटाबेस सत्र का क्लाइंट प्रतिनिधित्व है और डेटाबेस लेनदेन प्रदान करता है । कनेक्शन में किसी भी समय केवल एक ही लेन-देन खुला हो सकता है (लेकिन लेनदेन को नस्ट किया जा सकता है)
  • एक JDBC ResultSet एक भी द्वारा समर्थित है कर्सर डेटाबेस पर। जब ResultSet पर क्लोज़ () कॉल किया जाता है, तो कर्सर रिलीज़ होता है।
  • JDBC CallableStatement डेटाबेस पर संग्रहीत कार्यविधि को आमंत्रित करता है , जिसे अक्सर PL / SQL में लिखा जाता है। संग्रहीत प्रक्रिया शून्य या अधिक कर्सर बना सकती है, और एक JDBC परिणाम के रूप में एक कर्सर वापस कर सकती है।

JDBC थ्रेड सुरक्षित है: थ्रेड के बीच विभिन्न JDBC ऑब्जेक्ट्स को पास करना काफी ठीक है।

उदाहरण के लिए, आप एक थ्रेड में कनेक्शन बना सकते हैं; एक अन्य थ्रेड इस कनेक्शन का उपयोग एक रेडीस्टेमेंट बनाने के लिए कर सकता है और एक तीसरा धागा परिणाम सेट को संसाधित कर सकता है। एकल प्रमुख प्रतिबंध यह है कि आप किसी भी समय किसी भी तैयारी पर एक से अधिक ResultSet नहीं खोल सकते हैं। देखें कनेक्शन के प्रति क्या Oracle DB समर्थन एकाधिक (समानांतर) के संचालन?

ध्यान दें कि किसी कनेक्शन पर एक डेटाबेस कमिट होता है, और इसलिए उस कनेक्शन पर सभी DML (INSERT, UPDATE और DELETE) एक साथ काम करेंगे। इसलिए, यदि आप एक ही समय में कई लेनदेन का समर्थन करना चाहते हैं, तो आपके पास प्रत्येक समवर्ती लेनदेन के लिए कम से कम एक कनेक्शन होना चाहिए।

JDBC ऑब्जेक्ट्स को बंद करना

एक परिणाम निष्पादित करने का एक विशिष्ट उदाहरण है:

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) { }
}

ध्यान दें कि अंत में क्लोज़ द्वारा उठाए गए किसी भी अपवाद को कैसे अनदेखा किया जाता है ():

  • यदि आप केवल {} कैच {} के बिना रिजल्टसेट को बंद करते हैं, तो यह विफल हो सकता है और स्टेटमेंट को बंद होने से रोक सकता है
  • हम कॉलर को प्रचारित करने की कोशिश के शरीर में उठाए गए किसी भी अपवाद को अनुमति देना चाहते हैं। यदि आपके पास लूप ओवर है, उदाहरण के लिए, स्टेटमेंट बनाना और निष्पादित करना, तो लूप के भीतर प्रत्येक स्टेटमेंट को बंद करना याद रखें।

जावा 7 में, ओरेकल ने ऑटोक्लोसेबल इंटरफ़ेस पेश किया है जो जावा 6 बॉयलरप्लेट के अधिकांश को कुछ अच्छे सिंथैटिक चीनी के साथ बदल देता है।

होल्डिंग JDBC ऑब्जेक्ट्स

JDBC वस्तुओं को सुरक्षित रूप से स्थानीय चर, वस्तु उदाहरण और वर्ग के सदस्यों में रखा जा सकता है। यह आम तौर पर बेहतर अभ्यास है:

  • JDBC ऑब्जेक्ट्स को रखने के लिए ऑब्जेक्ट उदाहरण या वर्ग के सदस्यों का उपयोग करें जो कि एक लंबी अवधि में कई बार पुन: उपयोग किए जाते हैं, जैसे कि कनेक्शंस और रेडीमेड्स
  • रिजल्टसेट के लिए स्थानीय चरों का उपयोग करें क्योंकि ये प्राप्त किए जाते हैं, लूप किए जाते हैं और फिर एक फ़ंक्शन के दायरे में आम तौर पर बंद हो जाते हैं।

हालाँकि, एक अपवाद है: यदि आप EJB, या एक सर्वलेट / JSP कंटेनर का उपयोग कर रहे हैं, तो आपको एक सख्त थ्रेडिंग मॉडल का पालन करना होगा:

  • केवल एप्लिकेशन सर्वर थ्रेड बनाता है (जिसके साथ यह आने वाले अनुरोधों को संभालता है)
  • केवल एप्लिकेशन सर्वर कनेक्शन बनाता है (जो आप कनेक्शन पूल से प्राप्त करते हैं)
  • कॉल के बीच मान (स्थिति) को सहेजते समय, आपको बहुत सावधान रहना होगा। अपने स्वयं के कैश या स्थिर सदस्यों में मूल्यों को कभी भी संग्रहीत न करें - यह क्लस्टर और अन्य अजीब स्थितियों में सुरक्षित नहीं है, और एप्लिकेशन सर्वर आपके डेटा के लिए भयानक काम कर सकता है। इसके बजाय स्टेटफुल बीन्स या डेटाबेस का उपयोग करें।
  • विशेष रूप से, कभी नहीं पकड़ JDBC वस्तुओं (कनेक्शन, resultsets, PreparedStatements, आदि) विभिन्न दूरस्थ आमंत्रण से अधिक - अनुप्रयोग सर्वर इस का प्रबंधन करते हैं। एप्लिकेशन सर्वर न केवल एक कनेक्शन पूल प्रदान करता है, यह आपके रेडीस्टेमेंट्स को भी कैश करता है।

लीक को खत्म करना

JDBC लीक का पता लगाने और उसे खत्म करने में कई प्रक्रियाएं और उपकरण उपलब्ध हैं:

  1. विकास के दौरान - कीड़े को जल्दी पकड़ना अब तक का सबसे अच्छा तरीका है:

    1. विकास अभ्यास: अच्छे विकास अभ्यासों को आपके सॉफ़्टवेयर में बग्स की संख्या को कम करना चाहिए, इससे पहले कि वह डेवलपर के डेस्क को छोड़ दे। विशिष्ट प्रथाओं में शामिल हैं:

      1. जोड़ी प्रोग्रामिंग , पर्याप्त अनुभव के बिना उन लोगों को शिक्षित करने के लिए
      2. कोड समीक्षाएँ क्योंकि कई आँखें एक से बेहतर हैं
      3. इकाई परीक्षण जिसका अर्थ है कि आप किसी भी परीक्षण उपकरण से अपने सभी कोड आधार का उपयोग कर सकते हैं, जो प्रजनन को तुच्छ बनाता है
      4. अपने स्वयं के निर्माण के बजाय कनेक्शन पूलिंग के लिए मौजूदा पुस्तकालयों का उपयोग करें
    2. स्टैटिक कोड विश्लेषण: एक स्थिर कोड विश्लेषण करने के लिए उत्कृष्ट फाइंडबग्स जैसे टूल का उपयोग करें । यह उन कई स्थानों को उठाता है जहाँ पास () को सही ढंग से संभाला नहीं गया है। फाइंडबग्स में एक्लिप्स के लिए एक प्लगइन है, लेकिन यह वन-ऑफ़ के लिए स्टैंडअलोन भी चलाता है, जेनकिंस सीआई और अन्य बिल्ड टूल में एकीकरण है

  2. चलने के समय पर:

    1. धारणीयता और प्रतिबद्धता

      1. यदि ResultSet धारण क्षमता ResultSet.CLOSE_CURSORS_OVER_COMMIT है, तो ResultSet को बंद कर दिया जाता है जब Connection.commit () विधि कहा जाता है। यह Connection.setHoldability () का उपयोग करके या ओवरलोड किए गए Connection.createStatement () विधि का उपयोग करके सेट किया जा सकता है।
    2. रनटाइम पर लॉगिंग।

      1. अपने कोड में अच्छे लॉग स्टेटमेंट डालें। ये स्पष्ट और समझने योग्य होना चाहिए ताकि ग्राहक, सहयोगी स्टाफ और टीम के साथी प्रशिक्षण के बिना समझ सकें। उन्हें संक्षिप्त होना चाहिए और कुंजी चर और विशेषताओं के राज्य / आंतरिक मूल्यों को प्रिंट करना शामिल करना चाहिए ताकि आप प्रसंस्करण तर्क का पता लगा सकें। अच्छा लॉगिंग डिबगिंग अनुप्रयोगों के लिए मौलिक है, विशेष रूप से उन जिन्हें तैनात किया गया है।
      2. आप अपने प्रोजेक्ट के लिए एक डीबगिंग JDBC ड्राइवर जोड़ सकते हैं (डिबगिंग के लिए - वास्तव में इसे लागू न करें)। एक उदाहरण (मैंने इसका इस्तेमाल नहीं किया है) log4jdbc है । फिर आपको इस फ़ाइल पर कुछ सरल विश्लेषण करने की आवश्यकता है, जो यह देखता है कि एक समान पास नहीं है। यदि संभावित समस्या है, तो खुले और बंद को गिनना चाहिए

        1. डेटाबेस की निगरानी करना। SQL डेवलपर 'मॉनिटर SQL' फ़ंक्शन या क्वेस्ट के TOAD जैसे टूल का उपयोग करके अपने रनिंग एप्लिकेशन की निगरानी करें । इस लेख में निगरानी का वर्णन किया गया है । निगरानी के दौरान, आप खुले कर्सर (जैसे तालिका v $ sesstat से) को क्वेरी करते हैं और उनके SQL की समीक्षा करते हैं। यदि कर्सर की संख्या बढ़ रही है, और (सबसे महत्वपूर्ण बात) एक समान एसक्यूएल स्टेटमेंट पर हावी हो रही है, तो आप जानते हैं कि आपके पास उस एसक्यूएल के साथ एक रिसाव है। अपना कोड खोजें और समीक्षा करें।

अन्य विचार

क्या आप समापन कनेक्शन को संभालने के लिए WeakReferences का उपयोग कर सकते हैं?

कमजोर और नरम संदर्भ आपको एक वस्तु को संदर्भित करने की अनुमति देने के तरीके हैं जो किसी भी समय जेवीएम को कचरा इकट्ठा करने की अनुमति देता है, वह फिट बैठता है (यह मानते हुए कि उस वस्तु के लिए कोई मजबूत संदर्भ श्रृंखला नहीं है)।

यदि आप कंस्ट्रक्टर में एक रेफ़रक्यूवे को सॉफ्ट या कमजोर रेफ़रेंस में पास करते हैं, तो ऑब्जेक्ट GCFed होने पर ऑब्जेक्ट रेफ़क्यूक्यू में रखा जाता है जब यह होता है (यदि यह बिल्कुल होता है)। इस दृष्टिकोण के साथ, आप ऑब्जेक्ट के अंतिमकरण के साथ बातचीत कर सकते हैं और आप उस पल में ऑब्जेक्ट को बंद या अंतिम कर सकते हैं।

प्रेत संदर्भ थोड़ा अजीब हैं; उनका उद्देश्य केवल अंतिम रूप को नियंत्रित करना है, लेकिन आप कभी भी मूल वस्तु का संदर्भ प्राप्त नहीं कर सकते हैं, इसलिए इस पर करीबी () विधि को कॉल करना मुश्किल होगा।

हालांकि, जब जीसी चलाया जाता है, तो इसे नियंत्रित करने का प्रयास करना शायद ही कभी एक अच्छा विचार है (कमजोर, नरम और फैंटमरेफरेंस आपको इस तथ्य के बाद पता चलता है कि ऑब्जेक्ट जीसी के लिए संलग्न है)। वास्तव में, अगर JVM में मेमोरी की मात्रा बड़ी है (उदाहरण के लिए -Xmx2000m) तो आप कभी भी ऑब्जेक्ट को GC नहीं कर सकते हैं , और आप ORA-01000 का अनुभव करेंगे। यदि JVM मेमोरी आपके प्रोग्राम की आवश्यकताओं के सापेक्ष छोटी है, तो आप पा सकते हैं कि ResultSet और ReadyedStatement ऑब्जेक्ट्स निर्माण के तुरंत बाद GCed हैं (इससे पहले कि आप उनसे पढ़ सकें), जो संभवतः आपके प्रोग्राम को विफल कर देगा।

TL; DR: कमजोर संदर्भ तंत्र स्टेटमेंट और रिजल्ट ऑब्जेक्ट्स को प्रबंधित और बंद करने का एक अच्छा तरीका नहीं है।


3
यदि आप किसी लूप में स्टेटमेंट बनाते हैं, तो सुनिश्चित करें कि यह लूप में बंद है और आप केवल अंतिम स्टेटमेंट को बंद करेंगे।
तुलसीजाम

धन्यवाद, तुलसीजाम। आपके द्वारा बनाए गए बिंदु में जोड़ने के लिए उत्तर को संपादित करें।
एंड्रयू एल्कॉक

@ एंड्रयू एल्कॉक बहुत बहुत धन्यवाद! एंड्रयू। क्या आप 6 वें को भी जवाब दे सकते हैं।
कानूनगावु सुगुमार

@AndrewAlcock कृपया .. कृपया .. कृपया .. मेरे 7 वें प्रश्न का भी उत्तर दें। हमारे प्रोजेक्ट के बाद से हम लोड परीक्षण करते समय ORA-01000 का बहुत बार सामना कर रहे हैं। आपके इनपुट मेरे लिए अधिक मूल्यवान हैं। एक टन अग्रिम धन्यवाद !!
काणगावेलु सुगुमार

रे: 7 - आप grep जैसे उपकरण का उपयोग करके निकटता की खोज कर सकते हैं। जब आप एक SQL पहचानते हैं (चयन करें, डालें, अपडेट करें, हटाएं), कथन के निकट शब्द () की निकटता देखें। यदि निकटता अपेक्षा से अधिक दूर है, तो यह जांच का एक तरीका हो सकता है कि यह कहां गायब है। lightboxtechnologies.com/2012/07/27/…
Sun

28

मैं कुछ और समझ जोड़ रहा हूं।

  1. कर्सर केवल एक स्टेटमेंट के बारे में है; यह न तो resultSet है और न ही कनेक्शन ऑब्जेक्ट है।
  2. लेकिन फिर भी हमें कुछ दैवीय स्मृति को मुक्त करने के लिए परिणाम को बंद करना होगा। फिर भी यदि आप उन परिणामों को बंद नहीं करते हैं जो CURSORS के लिए नहीं गिने जाएंगे।
  3. क्लोजिंग स्टेटमेंट ऑब्जेक्ट स्वचालित रूप से रिजल्ट ऑब्जेक्ट को भी बंद कर देगा।
  4. सभी SELECT / INSERT / UPDATE / DELETE स्टेटमेंट के लिए कर्सर बनाया जाएगा।
  5. प्रत्येक ORACLE DB उदाहरण को ORID SID का उपयोग करके पहचाना जा सकता है; इसी तरह ORACLE DB कनेक्शन SID का उपयोग करके प्रत्येक कनेक्शन की पहचान कर सकता है। दोनों SID अलग हैं।
  6. इसलिए ORACLE सत्र एक jdbc (tcp) कनेक्शन के अलावा कुछ भी नहीं है; जो एक SID के अलावा कुछ नहीं है।
  7. यदि हम अधिकतम कर्सर 500 के रूप में सेट करते हैं तो यह केवल एक JDBC सत्र / कनेक्शन / SID के लिए है।
  8. तो हम कई संबंधित JDBC के साथ अपने संबंधित नहीं कर्सर (बयान) कर सकते हैं।
  9. एक बार JVM समाप्त हो जाने के बाद सभी कनेक्शन / शाप बंद हो जाएंगे, या JDBCConnection बंद है CURSORS के संबंध में उस कनेक्शन को बंद कर दिया जाएगा।

लोगिन को सिसदबा के रूप में।

पुट्टी में (ओरेकल लॉगिन):

  [oracle@db01 ~]$ sqlplus / as sysdba

SqlPlus में:

उपयोगकर्ता नाम: sys as sysdba

Session_cached_cursors को 0 पर सेट करें ताकि यह अभद्रता को बंद कर सके।

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

DB में प्रति कनेक्शन मौजूदा OPEN_CURSORS वैल्यू सेट चुनें

 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;

नीचे खुले कर्सर मूल्यों के साथ SID / कनेक्शन सूची खोजने के लिए क्वेरी है।

 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'

खुले कर्सर में sql की पहचान करने के लिए नीचे क्वेरी का उपयोग करें

 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'

अब कोड को डिबग करें और आनंद लें !!! :)


1
यहाँ एक और प्रश्न है जो अच्छी तरह से काम करता है: stackoverflow.com/a/2560415/32453
rogerdpack

4

अपना कोड इस तरह ठीक करें:

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()
} 

क्या आपको यकीन है, कि आप वास्तव में अपने pStatements, कनेक्शन और परिणाम बंद कर रहे हैं?

खुली वस्तुओं का विश्लेषण करने के लिए आप एक प्रतिनिधि पैटर्न को निहित कर सकते हैं, जो आपके स्टेटमंट, कनेक्शन और परिणाम वस्तुओं के चारों ओर कोड लपेटता है। तो आप देखेंगे, यदि कोई वस्तु सफलतापूर्वक बंद हो जाएगी।

के लिए एक उदाहरण: 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

यदि आपका एप्लिकेशन एक जावा ईई अनुप्रयोग सर्वर के रूप में Oracle WebLogic पर चल रहा है, तो इस समस्या का एक संभावित कारण WebLogic में स्टेटमेंट कैश आकार सेटिंग है।

यदि किसी विशेष डेटा स्रोत के लिए स्टेटमेंट कैश आकार की सेटिंग, Oracle डेटाबेस अधिकतम ओपन कर्सर काउंट सेटिंग के बराबर या उससे अधिक है, तो सभी खुले हुए कर्सर कैश्ड SQL स्टेटमेंट द्वारा खाए जा सकते हैं, जो WebLogic द्वारा खुले रखे गए हैं, जिसके परिणामस्वरूप ORA-01000 त्रुटि में।

इसे संबोधित करने के लिए, प्रत्येक WebLogic डेटा स्रोत के लिए स्टेटमेंट कैश आकार सेटिंग को कम करें जो Oracle डेटाबेस को इंगित करता है जो डेटाबेस पर अधिकतम कर्सर गणना सेटिंग से काफी कम है।

WebLogic 10 व्यवस्थापक कंसोल में, प्रत्येक डेटा स्रोत के लिए स्टेटमेंट कैश आकार सेटिंग सेवा (बाईं ओर)> डेटा स्रोत> (व्यक्तिगत डेटा स्रोत)> कनेक्शन पूल टैब पर पाया जा सकता है।


1
हाइबरनेट में स्टेटमेंट कैश भी होता है। डेवलपर को
पीनो

3

मैंने भी इस मुद्दे का सामना किया था। नीचे दिए गए अपवाद आते थे

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

मैं डाओ लेयर के लिए स्प्रिंग JDBC के साथ स्प्रिंग फ्रेमवर्क का उपयोग कर रहा था ।

मेरा आवेदन किसी तरह से और कुछ मिनटों के बाद, श्रापों को लीक करता था, यह मुझे यह अपवाद देता था।

पूरी तरह से डिबगिंग और विश्लेषण का एक बहुत बाद, मैंने पाया के साथ समस्या थी कि अनुक्रमण, प्राथमिक कुंजी और अद्वितीय प्रतिबन्ध में से एक में तालिका में इस्तेमाल किया जा रहा क्वेरी मैं क्रियान्वित किया गया था।

मेरा आवेदन उन स्तंभों को अद्यतन करने का प्रयास कर रहा था जो गलती से अनुक्रमित थे । इसलिए, जब भी मेरा आवेदन अनुक्रमित स्तंभों पर अद्यतन क्वेरी मार रहा था, डेटाबेस अद्यतन मूल्यों के आधार पर रीइन्डेक्सिंग करने की कोशिश कर रहा था। यह लीक किया गया था कर्सर

मैं उन स्तंभों पर समुचित अनुक्रमण करके समस्या का समाधान करने में सक्षम था, जिनका उपयोग क्वेरी में खोज करने के लिए किया गया था और जहाँ भी आवश्यक हो, उपयुक्त बाधाओं को लागू किया गया।


2

मैंने आज उसी समस्या (ORA-01000) का सामना किया। मेरे पास कोशिश में} के लिए लूप था}}, ओरेकल डीबी में कई बार एक सेलेक्ट स्टेटमेंट निष्पादित करने के लिए, (हर बार एक पैरामीटर बदलते हुए), और अंत में {} मेरे पास अपना परिणाम Resultset ,StedStatement और सामान्य रूप से बंद करने के लिए कोड था। । लेकिन जैसे ही मैं एक विशिष्ट मात्रा में छोरों (1000) तक पहुंचा, मुझे बहुत अधिक खुले कर्सर के बारे में ओरेकल त्रुटि मिली।

ऊपर एंड्रयू एंड्रयूक द्वारा पोस्ट के आधार पर, मैंने बदलाव किए ताकि लूप के अंदर , मैंने डेटा प्राप्त करने के बाद और फिर से लूप करने से पहले प्रत्येक परिणाम और प्रत्येक कथन को बंद कर दिया, और इससे समस्या हल हो गई।

अतिरिक्त, ठीक यही समस्या सम्मिलित विवरण के किसी अन्य लूप में, किसी अन्य Oracle DB (ORA-01000) में, इस बार 300 कथनों के बाद हुई। फिर से इसे उसी तरह से हल किया गया था, इसलिए या तो रेडीस्टेडमेंट या रिजल्टसेट या दोनों, खुले कर्सर के रूप में गिने जाएं, जब तक कि वे बंद न हो जाएं।


यह सही नहीं लगता। वसंत दस्तावेज़ कि यह ResultSets ( docs.spring.io/spring/docs/current/spring-framework-reference/… ) को बंद करने के लिए ज़िम्मेदार है ।
रियान

बस स्पष्टीकरण के लिए, उन उदाहरणों में मैं वसंत का उपयोग नहीं कर रहा था।
किन्निसन K

1

क्या आपने स्वतः पूर्णता = सत्य निर्धारित किया है? यदि यह कोशिश नहीं की:

{ //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 

क्या आप अन्य प्रश्नों के उत्तर भी दे सकते हैं?
काणगावेलु सुगुमार

2
ऑटोकॉमिट कनेक्शन को बंद नहीं करता है - यह केवल निष्पादन के तुरंत बाद प्रत्येक कथन को स्वचालित रूप से करता है। यदि आप ऑटोकॉमिट का उपयोग कर रहे हैं तो आपको डेटाबेस के सबसे महत्वपूर्ण गुणों में से एक से मूल्य नहीं मिल रहा है - लेनदेन। आप इसके बजाय NoSQL DB का उपयोग करने पर विचार कर सकते हैं।
एंड्रयू एल्कॉक

1

खुलने वाले sql को खोजने के लिए क्वेरी।

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

यह समस्या मुख्य रूप से तब होती है जब आप कनेक्शन पूलिंग का उपयोग कर रहे होते हैं क्योंकि जब आप कनेक्शन को बंद करते हैं तो कनेक्शन कनेक्शन पूल में वापस चला जाता है और उस कनेक्शन से जुड़े सभी कर्सर कभी भी बंद नहीं होते हैं क्योंकि डेटाबेस से कनेक्शन अभी भी खुला है। तो एक विकल्प पूल में कनेक्शन के निष्क्रिय कनेक्शन समय को कम करना है, इसलिए जब भी कनेक्शन 10 सेकंड के लिए कनेक्शन के लिए बेकार बैठता है, डेटाबेस से कनेक्शन बंद हो जाएगा और नया कनेक्शन पूल में डालने के लिए बनाया जाएगा।



0

हमारे मामले में, हम हाइबरनेट का उपयोग कर रहे थे और हमारे पास एक ही हाइबरनेट मैप्ड इकाई को संदर्भित करने वाले कई चर थे। हम इन संदर्भों को एक लूप में बना रहे थे और सहेज रहे थे। प्रत्येक संदर्भ ने एक कर्सर खोला और इसे खुला रखा।

हमने अपने कोड को चलाने के दौरान खुले कर्सर की संख्या की जांच करने के लिए एक क्वेरी का उपयोग करके , डिबगर के माध्यम से कदम रखते हुए और चुनिंदा टिप्पणी करते हुए इसका पता लगाया।

जैसे कि प्रत्येक नए संदर्भ ने एक और कर्सर क्यों खोला - सवाल में मौजूद इकाई को अन्य संस्थाओं के संग्रह में मैप किया गया था और मुझे लगता है कि इसके साथ कुछ करना था (शायद यह केवल अकेले नहीं है, लेकिन संयोजन में हमने कैसे प्राप्त किया है और हमने मोड प्राप्त किया है) कैश सेटिंग्स)। खुद हाइबरनेट में खुले श्रापों को बंद करने में विफल होने के आसपास कीड़े थे , हालांकि ऐसा लगता है कि ये बाद के संस्करणों में तय किए गए हैं।

चूंकि हमें वास्तव में एक ही इकाई के लिए इतने सारे डुप्लिकेट संदर्भों की आवश्यकता नहीं थी, इसलिए समाधान उन सभी अनावश्यक संदर्भों को बनाना और रोकना था। एक बार जब हमने वह समस्या दूर कर ली।


0

मुझे वाइल्डफली और टॉमकैट में अपने डेटा स्रोत के साथ यह समस्या थी, एक Oracle 10g से कनेक्ट करना।

मैंने पाया कि कुछ शर्तों के तहत बयान को तब भी बंद नहीं किया गया था जब statement.close () लागू किया गया था। समस्या ओरेकल ड्राइवर के साथ थी जिसका हम उपयोग कर रहे थे: ojdbc7.jar। यह ड्राइवर Oracle 12c और 11g के लिए अभिप्रेत है, और ऐसा लगता है कि Oracle 10g के साथ उपयोग किए जाने पर कुछ समस्याएँ हैं, इसलिए मैं ojdbc5.jar को डाउनग्रेड करता हूं और अब सब कुछ ठीक चल रहा है।


0

मुझे उसी समस्या का सामना करना पड़ा क्योंकि मैं 1000 से अधिक पुनरावृत्तियों के लिए db क्वेरी कर रहा था। मैंने अपने कोड में कोशिश और अंत में उपयोग किया है। लेकिन फिर भी त्रुटि हो रही थी।

इसे हल करने के लिए मैंने सिर्फ oracle db में लॉग इन किया और क्वेरी से नीचे चला गया:

ALTER SYSTEM SET open_cursors = 8000 SCOPE = BOTH;

और इससे मेरी समस्या तुरंत हल हो गई।


यह कुछ लक्षणों को सलाम करता है, लेकिन वास्तव में समस्या को हल नहीं करता है। आपको अपने कोड को ठीक करने की आवश्यकता है, ताकि यह उनके साथ समाप्त हो जाने पर कर्सर को बंद कर दे।
एपीसी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.