2009-08-20 9 views
52

मुझे Django अपने स्वयं के धागे में कुछ पुनरावर्ती कार्यों को चलाने के लिए स्थापित किया गया है, और मैंने देखा कि वे हमेशा अधूरा डेटाबेस कनेक्शन प्रक्रियाओं (pgsql "निष्क्रियता में निष्क्रिय) के पीछे छोड़ रहे थे।थ्रेडेड Django कार्य स्वचालित रूप से लेनदेन या डीबी कनेक्शन संभाल नहीं करता है?

मैंने पोस्टग्रेज़ लॉग देखे और पाया कि लेनदेन पूरा नहीं हो रहे थे (कोई रोलबैक नहीं)। मैंने अपने कार्यों पर विभिन्न लेनदेन सजावट का उपयोग करने की कोशिश की, कोई भाग्य नहीं।

मैं मैनुअल लेनदेन प्रबंधन में स्विच करने और रोलबैक मैन्युअल, जो काम किया था, लेकिन अभी भी "निष्क्रिय" के रूप में प्रक्रियाओं छोड़ दिया है।

तो फिर मैंने कनेक्शन.क्लोज़() कहा, और सब ठीक है।

लेकिन मैं छोड़ दिया सोच रहा हूँ, क्यों नहीं इन पिरोया कार्यों कि मुख्य Django धागे से पैदा किया जा रहा है के लिए Django के ठेठ लेनदेन और कनेक्शन प्रबंधन काम करता है?

उत्तर

93

परीक्षण और Django स्रोत कोड को पढ़ने के सप्ताह के बाद, मैं अपने ही सवाल का जवाब मिल गया है:

लेनदेन

Django के डिफ़ॉल्ट autocommit व्यवहार अभी भी मेरे थ्रेडेड समारोह के लिए सच है। हालांकि, यह Django डॉक्स में कहा गया है:

जैसे ही आप एक कार्रवाई डेटाबेस के लिए लिखने के लिए की जरूरत है कि प्रदर्शन के रूप में, Django सम्मिलित/अपडेट करने का उत्पादन/बयानों को हटाएं और फिर COMMIT है। कोई अंतर्निहित रोलबैक नहीं है।

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

इस तथ्य यह है कि PostgreSQL लेनदेन सोचता है के खिलाफ जाता है एक रोलबैक की आवश्यकता है। लॉग की समीक्षा में, मैंने खुद को फेंक दिया क्योंकि मैंने इन रोलबैक स्टेटमेंट को देखा और माना कि Django का लेनदेन प्रबंधन स्रोत था। बाहर निकलता है यह नहीं है, और यह ठीक है।

कनेक्शन

संबंध प्रबंधन है जहां चीजें मुश्किल हो रहा है। यह पता चला है कि Django signals.request_finished.connect(close_connection) का उपयोग करता है जो सामान्य रूप से उपयोग किए जाने वाले डेटाबेस कनेक्शन को बंद करता है। चूंकि डैंजो में आमतौर पर कुछ भी नहीं होता है जिसमें अनुरोध शामिल नहीं होता है, तो आप इस व्यवहार को मंजूरी देते हैं।

मेरे मामले में, हालांकि, कोई अनुरोध नहीं था क्योंकि नौकरी निर्धारित की गई थी। कोई अनुरोध का मतलब कोई सिग्नल नहीं है। कोई संकेत नहीं है कि डेटाबेस कनेक्शन कभी बंद नहीं हुआ था।

वापस लेन-देन के लिए जा रहे हैं, यह पता चला है कि बस लेन-देन प्रबंधन में कोई भी परिवर्तन के अभाव में connection.close() के लिए एक कॉल जारी करने PostgreSQL लॉग कि मैं की तलाश कर रहा था में ROLLBACK बयान जारी करता है।

समाधान

समाधान सामान्य Django लेनदेन प्रबंधन सामान्य रूप में आगे बढ़ने के लिए और बस कनेक्शन तीन तरीकों में से एक को बंद करने के लिए अनुमति देने के लिए है:

  1. एक डेकोरेटर कि कनेक्शन बंद कर देता है और लिखें इसमें आवश्यक कार्यों को लपेटें।
  2. Django कनेक्शन बंद करने के लिए मौजूदा अनुरोध सिग्नल में हुक।
  3. फ़ंक्शन के अंत में मैन्युअल रूप से कनेक्शन बंद करें।

इनमें से कोई भी तीन (और काम) करेगा।

इसने मुझे हफ्तों तक पागल कर दिया है। मुझे आशा है कि यह भविष्य में किसी और की मदद करेगा!

+1

खुशी है कि आपने अंततः इसे हल किया। यह स्पष्ट नहीं था। मुझे आश्चर्य है कि कहीं कहीं डॉक्स में एक नोट जोड़ने के लिए टिकट के लायक हो सकता है। –

+1

यह टिकट एक बहुत ही समान समस्या का वर्णन करता है: http://code.djangoproject.com/ticket/9964 – zooglash

+0

वाह। कोई मौका है कि आप कोड साझा कर सकते हैं? – Dejell

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