2009-10-29 11 views
20

मैं Django मॉडल में concurrency कैसे संभाल सकता हूं? मैं नहीं चाहता कि रिकॉर्ड में परिवर्तन दूसरे उपयोगकर्ता द्वारा ओवरराइट किया जा रहा है जो एक ही रिकॉर्ड पढ़ता है।Django मॉडल में Concurrency नियंत्रण

+0

http के संभावित डुप्लिकेट से लिया जाता है पंक्ति पर निहित db स्तर के अवरोध समाप्त: // stackoverflow .com/प्रश्न/320096/django-how-can-i-protect-विरुद्ध-समवर्ती-संशोधन-डेटाबेस-प्रविष्टियों – Tony

उत्तर

22

संक्षिप्त उत्तर, यह वास्तव में एक Django प्रश्न प्रस्तुत नहीं है।

Concurrency नियंत्रण अक्सर तकनीकी प्रश्न के रूप में प्रस्तुत किया जाता है, लेकिन कई तरीकों से कार्यात्मक आवश्यकताओं का सवाल है। आप कैसे काम करना चाहते हैं/काम करने के लिए अपने आवेदन की जरूरत है? जब तक हम उसे नहीं जानते, तब तक किसी भी Django- विशिष्ट सलाह देना मुश्किल होगा।

लेकिन, मुझे पर्यटन की तरह महसूस, इसलिए यहां आता है ...

दो सवाल है कि मैं अपने आप को पूछने के लिए जब संगामिति नियंत्रण के लिए जरूरत के साथ सामना करते हैं:

  • इसकी कितनी संभावना है कि दो उपयोगकर्ताओं को एक ही रिकॉर्ड को समवर्ती रूप से संशोधित करने की आवश्यकता होगी?
  • यदि उपयोगकर्ता के रिकॉर्ड में उनके संशोधन खो गए हैं तो उपयोगकर्ता पर क्या प्रभाव पड़ता है?

टकराव की संभावना अपेक्षाकृत अधिक है, या एक संशोधन को खोने का प्रभाव गंभीर है, तो आप निराशावादी लॉकिंग के कुछ फार्म को देखकर हो सकता है। एक निराशावादी योजना में, प्रत्येक उपयोगकर्ता को संशोधन के लिए रिकॉर्ड खोलने से पहले लॉजिकल लॉक प्राप्त करना होगा।

निराशावादी लॉकिंग बहुत जटिलता के साथ आता है। आपको ताले तक पहुंच सिंक्रनाइज़ करना होगा, गलती सहनशीलता पर विचार करना होगा, लॉक समाप्ति, ताले सुपर उपयोगकर्ताओं द्वारा ओवरराइड किया जा सकता है, क्या उपयोगकर्ता देख सकते हैं कि लॉक किसके पास है, इसी तरह और इसी तरह।

Django में, इसे लॉक रिकॉर्ड पर एक अलग लॉक मॉडल या किसी प्रकार के 'लॉक उपयोगकर्ता' विदेशी कुंजी के साथ कार्यान्वित किया जा सकता है। लॉक टेबल का उपयोग करके लॉक अधिग्रहण, उपयोगकर्ता, नोट्स इत्यादि के भंडारण के मामले में आपको थोड़ी अधिक लचीलापन मिलती है। यदि आपको किसी सामान्य लॉक टेबल की आवश्यकता होती है जिसका उपयोग किसी भी प्रकार के रिकॉर्ड को लॉक करने के लिए किया जा सकता है, तो फिर देखें django.contrib.contenttypes framework, लेकिन जल्दी से यह अमूर्त अंतरिक्ष यात्री सिंड्रोम में भंग कर सकते हैं।

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

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

Django के संदर्भ में, आशावादी संगामिति नियंत्रण निश्चित रूप से अपने मॉडल वर्ग पर विधि बचाने अधिभावी द्वारा लागू किया जा सकता ...

def save(self, *args, **kwargs): 
    if self.version != self.read_current_version(): 
     raise ConcurrentModificationError('Ooops!!!!') 
    super(MyModel, self).save(*args, **kwargs) 

और,, इन संगामिति तंत्र की या तो मजबूत होने के लिए, आप transactional control पर विचार करना होगा। यदि आप अपने लेनदेन के एसीआईडी ​​गुणों की गारंटी नहीं दे सकते हैं तो इन मॉडलों में से कोई भी पूरी तरह से काम करने योग्य नहीं है।

+0

ठीक है, आपने जो अंतिम उदाहरण लिखा था वह वह था जिसे मैं जानना चाहता था, इसलिए मुझे अपना खुद लिखना है मॉडल के लिए विधि बचाओ। मैं एक और ढांचे से आया हूं जब यह एक संपत्ति को "तुलनात्मक" करने के लिए एक संपत्ति स्थापित करने का मामला है, इसलिए मुझे नहीं पता था कि इसे Django में कैसे कार्यान्वित किया जाए, और मुझे शुरुआती ट्यूटोरियल में कोई उदाहरण नहीं मिला या मुझे याद आया। मैंने सोचा था कि चूंकि Django कई कार्यों को स्वचालित करता है कि अन्य ढांचे में प्रोग्रामर द्वारा किया जाता है, इस कार्य को पहले से पेश किए गए ढांचे में स्वचालित रूप से – Pablo

+0

हाँ प्रदान किया जा सकता है, मेरी व्यक्तिगत राय यह है कि ढांचे को सभी कार्यात्मकों के कारण इन डिजाइन पैटर्न को सामान्यीकृत करने से बचना चाहिए/तकनीकी प्रभाव। वाईएमएमवी ... –

+2

जैसा कि नीचे बताया गया है अंतिम स्निपेट में कोड टूटा हुआ है। संस्करण जांच और सहेजने के तरीके के बीच अभी भी एक संशोधन दिखाई दे सकता है। – julkiewicz

10

मुझे नहीं लगता कि 'संस्करण संख्या या टाइमस्टैम्प रखना' काम करता है।

self.version == self.read_current_version()True है, अभी भी एक मौका है कि संस्करण संख्या super().save() पर कॉल करने से पहले ही अन्य सत्रों द्वारा संशोधित की गई है।

+2

प्रश्न में तालिका को लॉक किए बिना, यह सही है। हालांकि, Django मॉडल के साथ टेबल लॉकिंग को सरल बनाने के लिए सजावटी हैं, जिन्हें आप जिस रेस स्थिति का जिक्र कर रहे हैं उससे बचें। – Cerin

2

मैं जो होलोय से प्रारंभिक स्पष्टीकरण से सहमत हूं।

मैं उसका जवाब के आखिरी हिस्से के लिए एक काम झलकी रिश्तेदार के साथ योगदान करने के लिए चाहते हैं ("Django के संदर्भ में, आशावादी संगामिति नियंत्रण अपने मॉडल वर्ग पर विधि बचाने अधिभावी द्वारा लागू किया जा सकता ...")

आप निम्न अजगर बयान सुरक्षित और संगत कर रहे हैं (एक बाहरी दायरे में transaction.atomic का उपयोग करके उदा।) अपने स्वयं के मॉडल

के लिए एक पूर्वज के रूप में निम्नलिखित वर्ग का उपयोग कर सकते आप एक डाटाबेस लेनदेन के अंदर कर रहे हैं

एक शॉट के माध्यम से अभ्यास में, बयान फ़िल्टर + अपडेट test_an का एक प्रकार प्रदान करता है रिकॉर्ड पर d_set: वे संस्करण को सत्यापित करते हैं और पंक्ति पर एक स्पष्ट रूप से डीबी-स्तर लॉक प्राप्त करते हैं। तो निम्न "सेव" रिकॉर्ड के फ़ील्ड को अपडेट करने में सक्षम है, यह सुनिश्चित करें कि यह एकमात्र सत्र है जो उस मॉडल इंस्टेंस पर चल रहा है। अंतिम प्रतिबद्ध (उदाहरण के transaction.atomic में __exit__ द्वारा स्वचालित रूप से निष्पादित करने के लिए)

class ConcurrentModel(models.Model): 
    _change = models.IntegerField(default=0) 

    class Meta: 
     abstract = True 

    def save(self, *args, **kwargs): 
     cls = self.__class__ 
     if self.pk: 
      rows = cls.objects.filter(
       pk=self.pk, _change=self._change).update(
       _change=self._change + 1) 
      if not rows: 
       raise ConcurrentModificationError(cls.__name__, self.pk) 
      self._change += 1 
     super(ConcurrentModel, self).save(*args, **kwargs) 

यह https://bitbucket.org/depaolim/optlock/src/ced097dc35d3b190eb2ae19853c2348740bc7632/optimistic_lock/models.py?at=default