2014-05-16 7 views
16

के लिए डेडलॉक पर पुनः प्रयास करें मैंने अभी कुछ समय खोजा है और मेरी समस्या का समाधान नहीं मिला है। हम कई बार हमारे परियोजना के लिए MySQL के साथ संयोजन के रूप में SQLAlchemy का उपयोग कर रहे हैं और हम मुठभेड़ खतरनाक त्रुटि:MySQL/SQLAlchemy

1213, 'Deadlock found when trying to get lock; try restarting transaction'.

हम इस मामले में सबसे तीन बार में लेन-देन को पुनः आरंभ करने की कोशिश करना चाहते हैं।

मैंने एक सजावट लिखना शुरू कर दिया है जो ऐसा करता है लेकिन मुझे नहीं पता कि विफल होने से पहले सत्र स्थिति को कैसे सहेजना है और उसके बाद उसी लेनदेन को फिर से प्रयास करना है? (SQLAlchemy एक रोलबैक की आवश्यकता के रूप में जब भी कोई अपवाद उठाया है)

मेरा काम अब तक,

def retry_on_deadlock_decorator(func): 
    lock_messages_error = ['Deadlock found', 'Lock wait timeout exceeded'] 

    @wraps(func) 
    def wrapper(*args, **kwargs): 
     attempt_count = 0 
     while attempt_count < settings.MAXIMUM_RETRY_ON_DEADLOCK: 
      try: 
       return func(*args, **kwargs) 
      except OperationalError as e: 
       if any(msg in e.message for msg in lock_messages_error) \ 
         and attempt_count <= settings.MAXIMUM_RETRY_ON_DEADLOCK: 
        logger.error('Deadlock detected. Trying sql transaction once more. Attempts count: %s' 
           % (attempt_count + 1)) 
       else: 
        raise 
      attempt_count += 1 
    return wrapper 
+1

क्या मैंने आपकी मदद की? या आपको एक और समाधान मिला। कृपया कोई परिणाम साझा करें। –

उत्तर

0

आप इस तरह कोड का उपयोग किया?

try: 

    Perform table transaction 
    break 
except: 
    rollback 
    delay 
    try again to perform table transaction 

The only way to truly handle deadlocks is to write your code to expect them. This generally isn't very difficult if your database code is well written. Often you can just put a try/catch around the query execution logic and look for a deadlock when errors occur. If you catch one, the normal thing to do is just attempt to execute the failed query again.

उपयोगी लिंक्स:

2

आप वास्तव में ऐसा नहीं कर सकते कि बाहर से Session के साथ। Session को आंतरिक रूप से इसका समर्थन करना होगा। इसमें बहुत से निजी राज्य की बचत शामिल होगी, इसलिए यह आपके समय के लायक नहीं हो सकता है।

मैंने निचले स्तर के स्क्लाक्लेमी कोर इंटरफ़ेस के पक्ष में अधिकांश ORM सामान को पूरी तरह से हटा दिया। उस (या यहां तक ​​कि किसी भी डीबीपीआई इंटरफ़ेस) का उपयोग करके आप पुनः प्रयास-जागरूक db.execute रैपर बनाने के लिए अपने retry_on_deadlock_decorator सजावटी (ऊपर प्रश्न देखें) का उपयोग कर सकते हैं।

@retry_on_deadlock_decorator 
def deadlock_safe_execute(db, stmt, *args, **kw): 
    return db.execute(stmt, *args, **kw) 

और

db.execute("UPDATE users SET active=0") 

के बजाय आप

deadlock_safe_execute(db, "UPDATE users SET active=0") 

जो स्वचालित रूप से फिर से प्रयास करेगा एक गतिरोध होता है अगर है।