2014-07-02 7 views
5

एकाधिक अपडेट समूह के लिए डेटाबेस लेनदेन का उपयोग करते समय, क्या मुझे लेनदेन के अंदर भी चयन शामिल करना चाहिए? उदाहरण के लिए, मान लीजिए कि मैं:क्या मुझे लेनदेन में SELECT को शामिल करना चाहिए?

  1. कि रिकॉर्ड के लिए एक रिकॉर्ड
  2. अनुमतियों की जांच संपादित मिलता है, कुछ रिकॉर्ड कुछ अन्य रिकॉर्ड

रिकॉर्ड

  • अद्यतन से डेटा का उपयोग कर
  • अद्यतन क्या मुझे "रिकॉर्ड प्राप्त करें" चरण से पहले या केवल अपडेट के आसपास लेनदेन शुरू करना चाहिए?

    मैं पोस्टग्रेस/Django transaction.atomic() का उपयोग कर रहा हूं लेकिन मुझे नहीं लगता कि यह यहां मायने रखता है।

  • उत्तर

    4

    संक्षिप्त संस्करण: "यह निर्भर करता है"।

    लंबे संस्करण:

    आप रीड-संशोधित-लिखने चक्र कर रहे हैं, तो न केवल यह एक सौदे में होना चाहिए, लेकिन आप किसी भी रिकॉर्ड आप बाद में संशोधित करने का इरादा SELECT ... FOR UPDATE चाहिए। अन्यथा आप खोए गए लिखने का जोखिम उठाने जा रहे हैं, जहां आप रिकॉर्ड पढ़ते समय और जब आपने अपडेट लिखा था, तो आप किसी और के अपडेट को ओवरराइट करते हैं।

    SERIALIZABLE लेनदेन अलगाव इससे भी मदद कर सकता है।

    आपको वास्तव में समेकन और अलगाव को समझने की आवश्यकता है। दुर्भाग्य से समझने के बिना केवल एकमात्र सरल, आसान "बस करें एक्स" जवाब यह है कि इसमें शामिल सभी तालिकाओं को लॉक करके प्रत्येक लेनदेन शुरू करना है। ज्यादातर लोग ऐसा नहीं करना चाहते हैं।

    मैं the tx isolation docs के पढ़ने (या दो, या तीन, या चार - यह कठिन सामग्री) का सुझाव देता हूं। दौड़ की स्थिति और संघर्ष बनाने के लिए समवर्ती psql सत्र (एकाधिक टर्मिनलों) के साथ प्रयोग।

    +1

    एक नोट Django उपयोगकर्ताओं के लिए: 'का चयन करें ... UPDATE' के लिए के माध्यम से उपलब्ध है Django का 'select_for_update' (https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.select_for_update) –

    +1

    @ScottStafford ... लेकिन दुर्भाग्यवश 'चयन करें ... साझा करने के लिए', या PostgreSQL की 'चयन ... कुंजी साझा करने के लिए' '' कुंजी अपडेट के लिए '। –

    +0

    तो, यह सुनिश्चित करने के लिए कि मैं Django कोण के साथ अनुवर्ती हूं, 'MyObject.objects.get (pk = 5) जैसे कॉल' 'license.atomic()' या नहीं के अंदर कुछ भी लॉक नहीं करेगा। ऐसा करने के लिए मुझे दोनों को 'banking.atomic()' के अंदर होना चाहिए और 'MyObject.objects.select_for_update() जैसे किसी फॉर्म का उपयोग करना है। यह सुनिश्चित करने के लिए कि MyObject 5 को तब तक बदला नहीं जा सकता मेरा लेनदेन समाप्त होता है। –

    1

    आदर्श रूप में (यदि संभव हो तो) यदि आप एक एकलdata-modifying CTE में अपने चार चरणों की सब करना होगा (जो स्वचालित रूप से एक एकल लेनदेन के अंदर होता है)।

    वह अभी भी दौड़ की स्थिति से इंकार नहीं करता है, बस उन्हें बहुत ही असंभव बनाता है, क्योंकि SELECT .. FOR UPDATE और बाद में UPDATE के बीच का समय सीमा कम हो जाती है। (हां, आपको अभी भी भारी समवर्ती पहुंच के तहत दौड़ की स्थिति का सामना करने के लिए FOR UPDATE (or another appropriate locking level) का उपयोग करना चाहिए।)

    यह Django जैसे वेब-फ्रेमवर्क के विशिष्ट (अक्षम) दृष्टिकोण नहीं है। लेकिन यह बेहतर दृष्टिकोण है। यह कई मायनों में प्रदर्शन का अनुकूलन:

    • डाटाबेस सर्वर से कम दौर यात्राएं (शायद सबसे महत्वपूर्ण)
    • को छोटा ताला बार जब SELECT .. FOR UPDATE का उपयोग कर
    • अनुमति दें Postgres प्रश्नों

    अनुकूलन करने के लिए डेटा-संशोधित सीटीई में, जागरूक रहें कि unreferenced CTEs are not executed at all, जो पंक्तियों को इच्छित रूप से लॉक नहीं करेगा।

    डेटा में सुधार करने वाले सीटीई के लिए कोड उदाहरण:

    There are many more on SO. Try a seach.

    +0

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

    +0

    @ScottStafford: एसक्यूएल या पीएल/पीजीएसक्यूएल सर्वर-साइड फ़ंक्शंस समान लाभ वाले कम डरावने विकल्प हो सकते हैं ... –

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