2012-03-21 10 views
12

मान लीजिए रोलबैक करने के लिए, मैं एक बदलाव बयान है:अजगर-mysql: जब स्पष्ट रूप से एक लेन-देन

cursor = conn.cursor() 
# some code 
affected_rows1 = cursor.execute(update_statement1, params1) 
# some code 
conn.commit() 
cursor.close() 

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

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

cursor = conn.cursor() 
# some code 
affected_rows1 = cursor.execute(update_statement1, params1) 
# some code 
affected_rows2 = cursor.execute(update_statement2, params2) 
#some code 
conn.commit() 
cursor.close() 

उत्तर

1

IMHO, आप लेन-देन रोलबैक करना चाहिए अगर आप एक ही कनेक्शन का उपयोग कर रहे हैं। जब आप लेनदेन खत्म करते हैं तो त्रुटि से पहले सब कुछ प्राप्त हो जाएगा। पकड़ने के अपवाद के लिए, मैं हमेशा MySQLdb.Error का उपयोग करता हूं लेकिन मुझे यकीन नहीं है कि यह सही है।

+0

मैं का उपयोग भी 'StandardError', और अब समझने के लिए सुनिश्चित करने के लिए सही है कोशिश कर रहा हूँ:

इस तरह आप आदर्श रूप में यह करना होगा है। – newtover

-1

इसकी उप-निष्पादन() को एक उप में लपेटने की सलाह दी गई है। यह मेरा इसे करने का तरीका है।

def executeSQL(self, stmt): 
    cursor = self.dbHand.cursor() 

    if not stmt.endswith(";"): 
     stmt += ';' 

    try: 
     cursor.execute(stmt) 
    except MySQLdb.Error, e: 
     self.logger.error("Caught MYSQL exception :%s: while executing stmt :%s:.\n"%(e,stmt)) 
     return False 
+1

मैं समझता हूं कि, मेरा प्रश्न हालांकि शर्तों के बारे में है जब अंतर्निहित 'रोलबैक' – newtover

+1

का आह्वान करना है, तो क्या आप इस विधि के लाभ को स्पष्ट कर सकते हैं? – Dikei

+0

@Dikei ने रोलबैक() का उल्लेख किया है, यदि MySQLdb.Error अपवाद पकड़ा गया है। – tuxuday

12

This link विभिन्न प्रकार की त्रुटियों को दिखाता है जिन्हें आप पकड़ सकते हैं। MySQLdb.Error मानक बेस क्लास है जिसमें से अन्य सभी MySQL त्रुटियां व्युत्पन्न होती हैं।

मैं आमतौर पर MySQLdb.Error का उपयोग करता हूं क्योंकि यह आपको MySQLdb से संबंधित त्रुटियों पर ध्यान केंद्रित करने देता है। इसके विपरीत StandardError लगभग सभी अपवादों को पकड़ लेगा (यदि आप बेहतर डिबगिंग क्षमता चाहते हैं तो कुछ नहीं चाहते हैं)। इसके अलावा MySQLdb.Error का उपयोग आपको सटीक त्रुटि संदेश (MySQL त्रुटि संख्या और सभी) प्रदर्शित करने की अनुमति देता है ताकि आप इसे तेज़ी से डीबग कर सकें।

प्रश्न के पहले भाग में आ रहा है, डेटाबेस विवरणों के मामले में यह त्रुटि के मामले में रोलबैक लेनदेन (यदि वे समर्थित हैं) के लिए आवश्यक है (आमतौर पर)।

मैं जिस पद्धति का पालन करता हूं वह क्लॉज को छोड़कर एक प्रयास में प्रत्येक execute कथन को लपेटना है (MySQLdb.Error को पकड़ना) और त्रुटि संदेश प्रिंट करने से पहले कोई त्रुटि होने पर रोलबैक का उपयोग करना और बाहर निकलना है।

हालांकि, एक पकड़ है। MySQLdb में जो परिवर्तन आप डीबी में करते हैं वे वास्तव में डेटाबेस तक लिखे गए हैं जब तक आप कॉल प्रतिबद्धता की व्याख्या नहीं करते। तो, तार्किक रूप से, रोलबैक आवश्यक नहीं है।

उदाहरण के लिए,

conn = MySQLdb.connection(db=, host=, passwd=, user=) 
cur = conn.cursor() 
#Say you have a table X with one entry id = 1 and total = 50 
cur.execute("update X set total = 70 where id = 1") 
#Actual DB has not yet changed 
cur.execute("update X set total = 80 where id = 1") 
#Actual DB has still not changed 

आप करने से बिना कार्यक्रम बाहर निकलते हैं, डीबी में मूल्य अभी भी 50 हो जाएगा क्योंकि आप कभी नहीं कहा जाता है प्रतिबद्ध()।

conn = MySQLdb.connection(db=, host=, passwd=, user=) 
cur = conn.cursor() 
#Say you have a table X with one entry id = 1 and total = 50 
try: 
    cur.execute("update X set total = 70 where id = 1") 
except MySQLdb.Error,e: 
    print e[0], e[1] 
    conn.rollback() 
    cur.close() 
    conn.close() 
    #print lengthy error description!! 
    sys.exit(2) 
    #Note: Value in table is still 50 
#If you do conn.commit() here, value becomes 70 in table too!! 
try: 
    cur.execute("update X set total = 80 where id = 1") 
except MySQLdb.Error,e: 
    print e[0], e[1] 
    conn.rollback() 
    cur.close() 
    conn.close() 
    #print lengthy error description!! 
    sys.exit(2) 
    #Value in DB will be 
    #a) 50 if you didn't commit anywhere 
    #b) 70 if you committed after first execute statement 
conn.commit() 
#Now value in DB is 80!! 
cur.close() 
conn.close() 
+0

एक मॉडल स्टैक ओवरफ्लो उत्तर (स्पष्टीकरण + पूरी तरह से काम करने वाला उदाहरण)। उत्तम। – Pyderman

+0

यदि प्रतिबद्ध() स्वयं किसी भी तरह विफल रहता है, तो execback() से परिवर्तनों को त्यागने के लिए रोलबैक() आवश्यक है ताकि अगली प्रतिबद्धता() (जो आपके उदाहरण में नहीं है) उन्हें नहीं मिलेगी? – Syncopated

+2

मानक और सुरक्षित अभ्यास का पालन किया जाना चाहिए: 'कोशिश करें {लेनदेन शुरू करें; बयान निष्पादित करें; लेनदेन प्रतिबद्ध;} पकड़ो (अपवाद ई) {रोलबैक प्रदर्शन; } अंत में {बयान जैसे डीबी संसाधन बंद करें; } 'यह भी बिंदु "_So, तार्किक रूप से, रोलबैक आवश्यक नहीं है ._" यदि प्रतिबद्ध नहीं होता है तो गलत है क्योंकि लेनदेन खुला रहता है और इससे किसी अन्य लेनदेन को पुनरारंभ करने जैसे गंभीर मुद्दों का सामना करना पड़ सकता है, जो कि अंतिम रूप से प्रतिबद्ध होगा आपने बंद नहीं किया है (वापस लुढ़का हुआ)। – sactiw

संबंधित मुद्दे