जब MySQLdb का उपयोग करते हुए शाप बंद करें


86

मैं एक WSGI वेब ऐप बना रहा हूं और मेरे पास एक MySQL डेटाबेस है। मैं MySQLdb का उपयोग कर रहा हूं, जो बयानों को निष्पादित करने और परिणाम प्राप्त करने के लिए अभिशाप प्रदान करता है। कर्सर को प्राप्त करने और बंद करने के लिए मानक अभ्यास क्या है? विशेष रूप से, मेरे श्राप कितने समय तक रहना चाहिए? क्या मुझे प्रत्येक लेनदेन के लिए एक नया कर्सर प्राप्त करना चाहिए?

मेरा मानना ​​है कि आपको कनेक्शन करने से पहले कर्सर को बंद करने की आवश्यकता है। क्या लेन-देन के सेटों को खोजने के लिए कोई महत्वपूर्ण लाभ है जो मध्यवर्ती कमिट की आवश्यकता नहीं है ताकि आपको प्रत्येक लेनदेन के लिए नए कर्सर प्राप्त करने की आवश्यकता न हो? क्या नए अभिशाप प्राप्त करने के लिए बहुत अधिक उपरि है, या यह सिर्फ एक बड़ी बात नहीं है?

जवाबों:


80

यह पूछने के बजाय कि मानक अभ्यास क्या है, क्योंकि यह अक्सर अस्पष्ट और व्यक्तिपरक होता है, आप मार्गदर्शन के लिए मॉड्यूल की तलाश कर सकते हैं। सामान्य तौर पर, withसुझाए गए उपयोगकर्ता के रूप में कीवर्ड का उपयोग करना एक शानदार विचार है, लेकिन इस विशिष्ट परिस्थिति में यह आपको अपेक्षित कार्यक्षमता नहीं दे सकता है।

मॉड्यूल के संस्करण 1.2.5 के रूप में, निम्न कोड ( जीथब ) के साथ संदर्भ प्रबंधक प्रोटोकॉल को MySQLdb.Connectionलागू करता है :

def __enter__(self):
    if self.get_autocommit():
        self.query("BEGIN")
    return self.cursor()

def __exit__(self, exc, value, tb):
    if exc:
        self.rollback()
    else:
        self.commit()

withपहले से ही कई मौजूदा प्रश्नोत्तर हैं , या आप पायथन के "स्टेटमेंट" के साथ समझ सकते हैं , लेकिन अनिवार्य रूप से ऐसा होता है कि ब्लॉक __enter__की शुरुआत में निष्पादित होता है with, और ब्लॉक __exit__छोड़ने पर निष्पादित होता है with। आप वैकल्पिक सिंटैक्स with EXPR as VARका उपयोग किसी ऑब्जेक्ट द्वारा लौटाए गए __enter__नाम से कर सकते हैं यदि आप उस ऑब्जेक्ट को बाद में संदर्भित करना चाहते हैं। इसलिए, ऊपर दिए गए कार्यान्वयन को देखते हुए, अपने डेटाबेस को क्वेरी करने का एक सरल तरीका है:

connection = MySQLdb.connect(...)
with connection as cursor:            # connection.__enter__ executes at this line
    cursor.execute('select 1;')
    result = cursor.fetchall()        # connection.__exit__ executes after this line
print result                          # prints "((1L,),)"

अब सवाल यह है कि withब्लॉक से बाहर निकलने के बाद कनेक्शन और कर्सर की स्थिति क्या है ? __exit__ऊपर दिखाई गई विधि केवल self.rollback()या तो कॉल करती है self.commit(), और उन विधियों में से कोई भी close()विधि कॉल करने के लिए नहीं जाती है। कर्सर का कोई भी __exit__तरीका निर्धारित नहीं है - और अगर यह किया तो कोई फर्क नहीं पड़ेगा, क्योंकि withकेवल कनेक्शन का प्रबंधन कर रहा है। इसलिए, withब्लॉक से बाहर निकलने के बाद कनेक्शन और कर्सर दोनों खुले रहते हैं । उपरोक्त उदाहरण में निम्नलिखित कोड जोड़कर यह आसानी से पुष्टि की जाती है:

try:
    cursor.execute('select 1;')
    print 'cursor is open;',
except MySQLdb.ProgrammingError:
    print 'cursor is closed;',
if connection.open:
    print 'connection is open'
else:
    print 'connection is closed'

आपको आउटपुट "कर्सर खुला है; कनेक्शन खुला है" देखना चाहिए।

मेरा मानना ​​है कि आपको कनेक्शन करने से पहले कर्सर को बंद करने की आवश्यकता है।

क्यों? MySQL सी एपीआई , जो आधार है MySQLdb, किसी भी कर्सर वस्तु को लागू नहीं करता है, मॉड्यूल दस्तावेज में निहित के रूप में: "MySQL कर्सर का समर्थन नहीं करता है, लेकिन, कर्सर को आसानी से नकल करते हैं।" दरअसल, MySQLdb.cursors.BaseCursorवर्ग सीधे विरासत में मिलता है objectऔर प्रतिबद्ध / रोलबैक के संबंध में अभिशापों पर इस तरह का कोई प्रतिबंध नहीं लगाता है। एक Oracle डेवलपर के पास यह कहने के लिए था :

cnx.commit () cur.close () से पहले मेरे लिए सबसे तार्किक लगता है। शायद आप नियम से जा सकते हैं: "यदि आपको इसकी आवश्यकता नहीं है तो कर्सर को बंद करें।" इस प्रकार कर्सर बंद करने से पहले प्रतिबद्ध ()। अंत में, कनेक्टर / पायथन के लिए, यह बहुत अंतर नहीं करता है, लेकिन या अन्य डेटाबेस यह हो सकता है।

मुझे उम्मीद है कि आप इस विषय पर "मानक अभ्यास" प्राप्त करने के करीब होंगे।

क्या लेन-देन के सेटों को खोजने के लिए कोई महत्वपूर्ण लाभ है जो मध्यवर्ती कमिट की आवश्यकता नहीं है ताकि आपको प्रत्येक लेनदेन के लिए नए कर्सर प्राप्त करने की आवश्यकता न हो?

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

क्या नए अभिशाप प्राप्त करने के लिए बहुत अधिक उपरि है, या यह सिर्फ एक बड़ी बात नहीं है?

ओवरहेड नगण्य है, और डेटाबेस सर्वर को बिल्कुल भी नहीं छूता है; यह पूरी तरह से MySQLdb के कार्यान्वयन के भीतर है। यदि आप एक नया कर्सर बनाते समय क्या हो रहा है, यह जानने के लिए वास्तव में उत्सुक हैं, तो आप गिटब पर देखBaseCursor.__init__ सकते हैं

पहले जब हम चर्चा कर रहे थे तब वापस जा रहे थे with, अब शायद आप समझ सकते हैं कि MySQLdb.Connectionकक्षा __enter__और __exit__विधियाँ आपको प्रत्येक में एक बिलकुल नया कर्सर ऑब्जेक्ट क्यों देती हैंwith ब्लॉक और इसे ट्रैक रखने या ब्लॉक के अंत में इसे बंद करने से परेशान नहीं करती हैं। यह काफी हल्का है और आपकी सुविधा के लिए पूरी तरह से मौजूद है।

यदि यह वास्तव में कर्सर ऑब्जेक्ट को micromanage करने के लिए आपके लिए महत्वपूर्ण है, तो आप इस तथ्य के लिए बनाने के लिए Referencelib.closing का उपयोग कर सकते हैं कि कर्सर ऑब्जेक्ट की कोई परिभाषित __exit__विधि नहीं है । उस मामले के लिए, आप इसका उपयोग कनेक्शन ऑब्जेक्ट को withब्लॉक से बाहर निकलने पर खुद को बंद करने के लिए मजबूर करने के लिए भी कर सकते हैं । यह आउटपुट "my_curs बंद है; my_conn बंद है":

from contextlib import closing
import MySQLdb

with closing(MySQLdb.connect(...)) as my_conn:
    with closing(my_conn.cursor()) as my_curs:
        my_curs.execute('select 1;')
        result = my_curs.fetchall()
try:
    my_curs.execute('select 1;')
    print 'my_curs is open;',
except MySQLdb.ProgrammingError:
    print 'my_curs is closed;',
if my_conn.open:
    print 'my_conn is open'
else:
    print 'my_conn is closed'

ध्यान दें कि with closing(arg_obj)तर्क ऑब्जेक्ट __enter__और __exit__विधियों को कॉल नहीं करेगा ; इसे केवल तर्क वस्तु कहेंगेclosewith ब्लॉक के अंत में विधि को । (कार्रवाई में यह देखने के लिए, बस एक वर्ग को परिभाषित Fooके साथ __enter__, __exit__और closeतरीकों सरल युक्त printबयान, और तुलना क्या होता है जब आप करते हैं with Foo(): passक्या होता है जब आप क्या करनाwith closing(Foo()): pass है।) इस दो महत्वपूर्ण प्रभाव पड़ता है:

सबसे पहले, यदि ऑटोकॉमिट मोड सक्षम है, तो MySQLdb BEGINसर्वर पर एक स्पष्ट लेन-देन करेगा जब आप उपयोग करते हैं with connectionऔर ब्लॉक के अंत में लेनदेन को कमिट या रोलबैक करते हैं। ये MySQLdb के डिफ़ॉल्ट व्यवहार हैं, जिसका उद्देश्य आपको MySQL के डिफ़ॉल्ट व्यवहार से तत्काल किसी भी और सभी DML स्टेटमेंट को सुरक्षित रखना है। MySQLdb मानता है कि जब आप एक संदर्भ प्रबंधक का उपयोग करते हैं, तो आप एक लेनदेन चाहते हैं, और BEGINसर्वर पर ऑटोकॉमिट सेटिंग को बायपास करने के लिए स्पष्ट का उपयोग करता है। यदि आप उपयोग करने के लिए उपयोग किए जाते हैं with connection, तो आप सोच सकते हैं कि ऑटोकॉमिट अक्षम है जब वास्तव में यह केवल बायपास किया जा रहा था। यदि आप जोड़ते हैं तो आपको एक अप्रिय आश्चर्य हो सकता हैclosingअपने कोड के लिए और लेनदेन अखंडता खो; आप परिवर्तनों को रोलबैक करने में सक्षम नहीं होंगे, आप संक्षिप्तता बग देखना शुरू कर सकते हैं और यह तुरंत स्पष्ट नहीं हो सकता है कि क्यों।

दूसरा, with closing(MySQLdb.connect(user, pass)) as VARबांधता कनेक्शन वस्तु को VARकरने के लिए, इसके विपरीत में with MySQLdb.connect(user, pass) as VAR, जो बांधता है एक नया कर्सर वस्तु कोVAR । उत्तरार्द्ध मामले में आपके पास कनेक्शन ऑब्जेक्ट तक कोई सीधी पहुंच नहीं होगी! इसके बजाय, आपको कर्सर की connectionविशेषता का उपयोग करना होगा , जो मूल कनेक्शन तक प्रॉक्सी पहुंच प्रदान करता है। जब कर्सर बंद हो जाता है, तो इसकी connectionविशेषता सेट की जाती है None। यह एक परित्यक्त कनेक्शन का परिणाम है जो निम्नलिखित में से एक होने तक चारों ओर चिपक जाएगा:

  • कर्सर के सभी संदर्भ हटा दिए जाते हैं
  • कर्सर दायरे से बाहर चला जाता है
  • कनेक्शन बार बाहर
  • सर्वर प्रशासन उपकरण के माध्यम से कनेक्शन मैन्युअल रूप से बंद है

आप खुले कनेक्शनों की निगरानी के द्वारा (Workbench में या द्वारा इस परीक्षण कर सकते हैं का उपयोग करSHOW PROCESSLIST ) एक के बाद निम्नलिखित लाइनों एक निष्पादित करते समय:

with MySQLdb.connect(...) as my_curs:
    pass
my_curs.close()
my_curs.connection          # None
my_curs.connection.close()  # throws AttributeError, but connection still open
del my_curs                 # connection will close here

14
आपकी पोस्ट सबसे अधिक थकाऊ थी, लेकिन फिर भी इसे कुछ बार पढ़ने के बाद, मैं अपने आप को अभी भी शाप देने वालों के बारे में हैरान हूँ। इस विषय पर कई पोस्ट को देखते हुए, यह भ्रम की एक आम बात है। मेरा तात्पर्य यह है कि शाप देने वालों को उचित रूप से .close () की आवश्यकता नहीं होती है - जिसे कभी भी कहा जाता है। तो भी .close () विधि क्यों है?
SMGreenfield

6
संक्षिप्त उत्तर यह है कि पायथन डीबी एपीआईcursor.close() का एक हिस्सा है , जिसे विशेष रूप से MySQL को ध्यान में रखकर नहीं लिखा गया था।
एयर

1
डेल my_curs के बाद कनेक्शन बंद क्यों होगा?
बीएई

@ChengchengPei वस्तु my_cursका अंतिम संदर्भ रखती है connection। एक बार वह संदर्भ मौजूद नहीं है, तो connectionवस्तु को कचरा एकत्र किया जाना चाहिए
एयर

यह एक शानदार जवाब है, धन्यवाद। के उत्कृष्ट स्पष्टीकरण withऔर MySQLdb.Connectionकी __enter__और __exit__कार्य करता है। फिर से, धन्यवाद @Air।
यूजीन

33

To कीवर्ड ’के साथ इसका उपयोग करके इसे फिर से लिखना बेहतर है। 'के साथ' बंद कर्सर के बारे में ध्यान रखेगा (यह महत्वपूर्ण है क्योंकि यह अप्रबंधित संसाधन है) स्वचालित रूप से। लाभ यह है कि अपवाद के मामले में यह कर्सर को बंद कर देगा।

from contextlib import closing
import MySQLdb

''' At the beginning you open a DB connection. Particular moment when
  you open connection depends from your approach:
  - it can be inside the same function where you work with cursors
  - in the class constructor
  - etc
'''
db = MySQLdb.connect("host", "user", "pass", "database")
with closing(db.cursor()) as cur:
    cur.execute("somestuff")
    results = cur.fetchall()
    # do stuff with results

    cur.execute("insert operation")
    # call commit if you do INSERT, UPDATE or DELETE operations
    db.commit()

    cur.execute("someotherstuff")
    results2 = cur.fetchone()
    # do stuff with results2

# at some point when you decided that you do not need
# the open connection anymore you close it
db.close()

मुझे नहीं लगता कि withयह एक अच्छा विकल्प है यदि आप इसे फ्लास्क या अन्य वेब फ्रेमवर्क में उपयोग करना चाहते हैं। अगर स्थिति है http://flask.pocoo.org/docs/patterns/sqlite3/#sqlite3तो समस्याएं होंगी।
जेम्स किंग

@ जेम्स-राजा मैंने फ्लास्क के साथ काम नहीं किया, लेकिन आपके उदाहरण में फ्लास्क डीबी कनेक्शन को बंद कर देगा। वास्तव में मेरे कोड में मैं थोड़ा अलग approach- मैं उपयोग का उपयोग के साथ करीब कर्सर के लिए with closing(self.db.cursor()) as cur: cur.execute("UPDATE table1 SET status = %s WHERE id = %s",(self.INTEGR_STATUS_PROCESSING, id)) self.db.commit()
रोमन Podlinov

@RomanPodlinov हाँ, यदि आप इसे कर्सर के साथ उपयोग करते हैं तो चीजें ठीक होंगी।
जेम्स राजा

7

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

सबसे पहले, कुछ तथ्य:

  • पाइथन के withसिंटैक्स ब्लॉक __enter__के शरीर को निष्पादित करने से पहले संदर्भ प्रबंधक की विधि withऔर उसके __exit__बाद की विधि को कहते हैं।
  • कनेक्शन में एक __enter__विधि होती है जो एक कर्सर बनाने और वापस करने के अलावा कुछ भी नहीं करती है, और एक __exit__विधि जो या तो कमिट करती है या वापस रोल करती है (यह निर्भर करता है कि क्या अपवाद फेंक दिया गया था)। यह कनेक्शन को बंद नहीं करता है
  • PyMySQL में कर्सर विशुद्ध रूप से पायथन में लागू किया गया एक अमूर्त है; MySQL में कोई समान अवधारणा नहीं है। 1
  • कर्सर एक __enter__ऐसी __exit__विधि है जो कुछ भी नहीं करती है और एक विधि जो कर्सर को "बंद" करती है (जिसका अर्थ है कि कर्सर को उसके मूल कनेक्शन के संदर्भ को शून्य करना और कर्सर पर संग्रहीत किसी भी डेटा को फेंक देना)।
  • कर्सर कनेक्शन के संदर्भ का संदर्भ देते हैं, जो उन्हें पैदा करता है, लेकिन कनेक्शन उन कर्सरों के संदर्भ को नहीं पकड़ते हैं जो उन्होंने बनाए हैं।
  • कनेक्शन में एक __del__विधि होती है जो उन्हें बंद कर देती है
  • प्रति https://docs.python.org/3/reference/datamodel.html , CPython (डिफ़ॉल्ट पायथन कार्यान्वयन) संदर्भ गिनती का उपयोग करता है और स्वचालित रूप से एक वस्तु को हटा देता है, जब संदर्भ की संख्या शून्य हो जाती है।

इन चीजों को एक साथ रखकर, हम देखते हैं कि इस तरह के भोले कोड सिद्धांत समस्याग्रस्त हैं:

# Problematic code, at least in theory!
import pymysql
with pymysql.connect() as cursor:
    cursor.execute('SELECT 1')

# ... happily carry on and do something unrelated

समस्या यह है कि कुछ भी कनेक्शन बंद नहीं हुआ है। दरअसल, यदि आप ऊपर दिए गए कोड को पायथन शेल में चिपकाते हैं और फिर SHOW FULL PROCESSLISTMySQL शेल में चलाते हैं , तो आप अपने द्वारा बनाए गए निष्क्रिय कनेक्शन को देख पाएंगे। चूंकि कनेक्शन के MySQL की डिफ़ॉल्ट संख्या 151 है , जो बहुत बड़ी नहीं है , यदि आप इन कनेक्शनों को खुला रखते हुए कई प्रक्रियाएँ करते हैं, तो आप सैद्धांतिक रूप से समस्याओं में भागना शुरू कर सकते हैं।

हालाँकि, CPython में, एक बचत अनुग्रह है जो यह सुनिश्चित करता है कि ऊपर मेरे उदाहरण की तरह कोड संभवत : खुले कनेक्शनों के भार को छोड़ने का कारण नहीं बनेगा। अनुग्रह की बचत यह है कि जैसे ही cursorयह कार्यक्षेत्र से बाहर हो जाता है (जैसे कि वह फ़ंक्शन जिसमें इसे खत्म किया गया था, या cursorइसे सौंपा गया एक और मान प्राप्त हुआ है), इसकी संदर्भ संख्या शून्य से टकराती है, जिसके कारण कनेक्शन का संदर्भ गणना समाप्त हो जाती है शून्य करने के लिए, कनेक्शन की __del__विधि को बुलाया जाता है जो कनेक्शन को बल से बंद कर देता है। यदि आपने पहले ही अपने पायथन शेल में ऊपर दिए गए कोड को चिपका दिया है, तो अब आप इसे चलाकर अनुकरण कर सकते हैं cursor = 'arbitrary value'; जैसे ही आप ऐसा करते हैं, आपके द्वारा खोला गया कनेक्शन SHOW PROCESSLISTआउटपुट से गायब हो जाएगा ।

हालाँकि, इस पर निर्भर होना एक अमानवीय है, और सैद्धांतिक रूप से पायथन कार्यान्वयन में CPython के अलावा अन्य विफल हो सकता है। क्लीनर, सिद्धांत रूप में, स्पष्ट रूप .close()से कनेक्शन होगा (ऑब्जेक्ट को नष्ट करने के लिए पायथन की प्रतीक्षा किए बिना डेटाबेस पर एक कनेक्शन को मुक्त करने के लिए)। यह अधिक मजबूत कोड इस तरह दिखता है:

import contextlib
import pymysql
with contextlib.closing(pymysql.connect()) as conn:
    with conn as cursor:
        cursor.execute('SELECT 1')

यह बदसूरत है, लेकिन आपके (डेटाबेस की उपलब्ध उपलब्ध संख्या) डेटाबेस कनेक्शन को मुक्त करने के लिए अपनी वस्तुओं को नष्ट करने वाले पायथन पर भरोसा नहीं करता है।

ध्यान दें कि कर्सर को बंद करना यदि आप पहले से ही इस तरह से कनेक्शन बंद कर रहे हैं, तो बंद करना, पूरी तरह से व्यर्थ है।

अंत में, यहां दिए गए माध्यमिक प्रश्नों के उत्तर देने के लिए:

क्या नए अभिशाप प्राप्त करने के लिए बहुत अधिक उपरि है, या यह सिर्फ एक बड़ी बात नहीं है?

नहीं, तत्काल एक कर्सर MySQL बिल्कुल नहीं मारा और मूल रूप से कुछ भी नहीं करता है

क्या लेन-देन के सेटों को खोजने के लिए कोई महत्वपूर्ण लाभ है जो मध्यवर्ती कमिट की आवश्यकता नहीं है ताकि आपको प्रत्येक लेनदेन के लिए नए कर्सर प्राप्त करने की आवश्यकता न हो?

यह एक सामान्य उत्तर देने के लिए स्थितिजन्य और कठिन है। जैसा कि https://dev.mysql.com/doc/refman/en/optimizing-innodb-transaction-management.html इसे डालता है, "एक एप्लिकेशन प्रदर्शन समस्याओं का सामना कर सकता है यदि यह प्रति सेकंड हजारों बार, और अलग-अलग प्रदर्शन मुद्दों पर हो तो यह केवल हर 2-3 घंटे में शुरू होता है ” । आप हर कमिटमेंट के लिए एक ओवरहेड भुगतान करते हैं, लेकिन अधिक समय तक लेन-देन को खुला छोड़ते हुए, आप अन्य कनेक्शनों की संभावना बढ़ाते हैं, जो ताले के इंतजार में समय बिताते हैं, आपके गतिरोध के जोखिम को बढ़ाते हैं, और संभवतः अन्य कनेक्शनों द्वारा किए गए कुछ लुकअप की लागत में वृद्धि करते हैं। ।


1 MySQL में एक निर्माण होता है जिसे एक कर्सर कहते हैं लेकिन वे केवल संग्रहीत प्रक्रियाओं के अंदर मौजूद होते हैं; वे PyMySQL कर्सर के लिए पूरी तरह से अलग हैं और यहां प्रासंगिक नहीं हैं।


5

मुझे लगता है कि आप अपने सभी निष्पादन के लिए एक कर्सर का उपयोग करने से बेहतर होंगे, और इसे अपने कोड के अंत में बंद कर देंगे। इसके साथ काम करना आसान है, और इसमें दक्षता लाभ भी हो सकते हैं (मुझे उस पर उद्धरण न दें)।

conn = MySQLdb.connect("host","user","pass","database")
cursor = conn.cursor()
cursor.execute("somestuff")
results = cursor.fetchall()
..do stuff with results
cursor.execute("someotherstuff")
results2 = cursor.fetchall()
..do stuff with results2
cursor.close()

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

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


धन्यवाद - यह ध्यान में रखते हुए कि आपको अपडेट / इंसर्ट करने के लिए कर्सर को बंद करना है, मुझे लगता है कि अपडेट / इंसर्ट के लिए इसे करने का एक आसान तरीका यह है कि प्रत्येक डेमन के लिए एक कर्सर मिलेगा, कमिट करने के लिए कर्सर को बंद करें और तुरंत एक नया कर्सर प्राप्त करें तो अगली बार आपका तैयार है। क्या यह उचित है?
१०:२१ बजे जूलोय

1
अरे, कोई बात नहीं। मुझे वास्तव में आपके कर्सर को बंद करने से अद्यतन / सम्मिलित करने के बारे में पता नहीं था, लेकिन एक त्वरित खोज ऑनलाइन यह दिखाती है: con = MySQLdb.connect (तर्क_go_here) कर्सर = MySQLdb.cursor () कर्सर। यदि त्रुटि होती है, तो () को छोड़कर: con.rollback () # पूर्ववत परिवर्तन। इस तरह, डेटाबेस स्वयं परिवर्तनों को लागू करता है, और आपको स्वयं को अभिशापों के बारे में चिंता करने की आवश्यकता नहीं है। तब आपके पास हर समय 1 कर्सर खुला रह सकता है। यहाँ एक नज़र है: Tutorialspoint.com/python/python_database_access.htm
nct25

हाँ, अगर वह काम करता है तो मैं सिर्फ गलत हूँ और कुछ अन्य कारण थे जिसके कारण मुझे लगा कि मुझे कनेक्शन करने के लिए कर्सर बंद करना पड़ा है।
१०:३१ पर jillonoy

हाँ, मुझे पता नहीं, मैंने जो लिंक पोस्ट किया है, वह मुझे लगता है कि काम करता है। मुझे लगता है कि थोड़ा और शोध आपको बताएगा कि यह निश्चित रूप से काम करता है या नहीं, लेकिन मुझे लगता है कि आप शायद इसके साथ जा सकते हैं। आशा है कि मैं आपकी मदद कर रहा था!
nct25

कर्सर थ्रेड-सुरक्षित नहीं है, यदि आप कई अलग-अलग थ्रेड्स के बीच एक ही कर्सर का उपयोग करते हैं, और वे सभी db से प्राप्त कर रहे हैं, fetchall () यादृच्छिक डेटा देगा।
ospider

-6

मैं इसे php और mysql की तरह करने का सुझाव देता हूं। पहले डेटा की छपाई से पहले अपने कोड की शुरुआत में मुझे शुरू करें। तो अगर आपको एक कनेक्ट त्रुटि मिलती है तो आप एक प्रदर्शित कर सकते हैं 50x(याद नहीं रखें कि आंतरिक त्रुटि क्या है) त्रुटि संदेश। और इसे पूरे सत्र के लिए खुला रखें और इसे बंद कर दें जब आपको पता हो कि आपको इसकी आवश्यकता नहीं है।


MySQLdb में, कनेक्शन और कर्सर के बीच अंतर होता है। मैं अनुरोध के लिए एक बार (अभी के लिए) कनेक्ट करता हूं और जल्दी से कनेक्शन त्रुटियों का पता लगा सकता हूं। लेकिन अभिशापों के बारे में क्या?
२०:

IMHO यह सटीक सलाह नहीं है। यह निर्भर करता है। यदि आपका कोड लंबे समय तक कनेक्शन रखेगा (जैसे कि यह DB से कुछ डेटा लेता है और फिर 1-5-10 मिनट के लिए यह सर्वर पर कुछ करता है और कनेक्शन रखता है) और यह मल्टी थ्रेड एप्लिकेशन है जो बहुत जल्द एक समस्या पैदा करेगा (आप अधिकतम स्वीकृत कनेक्शन से अधिक हो जाएगा)।
रोमन पोडलिनोव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.