2012-04-18 8 views
5

मेरे पास चालान के लिए एक सास पालतू परियोजना है। इसमें, मैं अपने ग्राहकों को टिकट संख्या 1001 के साथ प्रत्येक शुरुआत करना चाहता हूं। जाहिर है, मैं पोस्टग्रेज़ में एक साधारण ऑटो फ़ील्ड का उपयोग नहीं कर सकता और केवल मूल्य में 1000 जोड़ सकता हूं, क्योंकि मेरे सभी ग्राहक एक ही डेटाबेस साझा करेंगे और उसी tickets तालिका .. मैंने नवीनतम नंबर प्राप्त करने के लिए एक पूर्णांक कॉलम प्रकार और क्वेरीिंग (छद्म एसक्यूएल) SELECT LATEST number FROM tickets WHERE client_id = [current client ID] का उपयोग करने का प्रयास किया है, और उसके बाद अगले number प्राप्त करने के लिए उस नंबर + 1 का उपयोग कर रहा है। समस्या यह है कि समेकन के साथ, दो टिकटों के लिए इस तरह की संख्या के साथ समाप्त होना आसानी से संभव है। जिस नंबर को मुझे Django के भीतर या कच्चे एसक्यूएल (बैश या सॉर्ट के किसी और चीज का उपयोग करके) करने में सक्षम होना चाहिए।पोस्टग्रेस में कॉलम मैन्युअल रूप से अनुक्रमित करने का उचित तरीका क्या है?

मैं काम करने के लिए अपने उदाहरण को मजबूर करने का कोई तरीका नहीं ढूंढ रहा हूं। मैं बस प्रत्येक ग्राहक के लिए स्वतंत्र रूप से बढ़ती टिकट संख्या की आवश्यकता की मेरी समस्या का हल ढूंढ रहा हूं।

+1

संभावित डुप्ली: http://stackoverflow.com/questions/6046085/postgresql-sequence-that-ensure-a-unique-id –

+0

डुप्लिकेट नहीं है क्योंकि यह एक अद्वितीय संख्या की तलाश में है। मेरा दूसरा क्षेत्र (क्लाइंट फ़ील्ड) के संबंध में अनुक्रम में अगली संख्या की तलाश में है। असल में, मेरा कहना है कि मैं एक ऑटो फील्ड (यानी, धारावाहिक) का उपयोग नहीं कर सकता। – orokusaki

+0

गोचा, अब मैं समझता हूं। उम्मीद है कि मेरा जवाब आपके लिए काम करता है (या, बेहतर अभी तक, किसी और के पास कुछ और सुरुचिपूर्ण है)। –

उत्तर

5

मुझे नहीं लगता कि इस समस्या का "सस्ता" समाधान है। बहु-उपयोगकर्ता वातावरण में सुरक्षित (लेकिन जरूरी नहीं) एकमात्र समाधान प्रत्येक ग्राहक के लिए एक पंक्ति के साथ "काउंटर" तालिका होना है।

UPDATE cust_numbers 
    SET current_number = current_number + 1 
WHERE cust_id = 42 
RETURNING current_number; 

कि एक चरण में तीन बातें करते हैं

  1. वृद्धि वर्तमान "अनुक्रमिक" होगा:

    प्रत्येक लेनदेन पहले एक नया टिकट, कुछ इस तरह डालने से पहले ग्राहक की प्रविष्टि लॉक करने के लिए है उस ग्राहक के लिए संख्या

  2. पंक्ति को लॉक करें ताकि अन्य लेन-देन करने के लिए उसे लॉक
  3. का नया मूल्य वापस कर देना होगा कॉलम पर

उस नए नंबर के साथ अब आप एक नया टिकट डाल सकते हैं। यदि लेनदेन किया गया है, तो यह cust_numbers तालिका पर लॉक भी जारी करेगा, इस प्रकार अन्य लेनदेन "किसी संख्या की प्रतीक्षा" आगे बढ़ सकते हैं।

आप एक ही संग्रहीत फ़ंक्शन में दो चरणों (अपडेट .. & डालने) को लपेट सकते हैं ताकि इसके पीछे तर्क केंद्रीकृत हो। टिकट संख्या उत्पन्न होने के बारे में जानने के बिना आपका आवेदन केवल select insert_ticket(...) पर कॉल करेगा।

यदि कोई नया ग्राहक बनाया गया है तो आप cust_numbers तालिका में स्वचालित रूप से पंक्ति को सम्मिलित करने के लिए ग्राहक तालिका पर एक ट्रिगर भी बनाना चाहेंगे।

इसका नुकसान यह है कि आप उसी ग्राहक के लिए नए टिकट डालने वाले लेनदेन को प्रभावी ढंग से क्रमबद्ध करते हैं। आपके सिस्टम में आवेषण की मात्रा के आधार पर यह एक प्रदर्शन समस्या हो सकती है।

संपादित
इस का एक और नुकसान है, कि तुम मजबूर टिकट कि जिस तरह से जो समस्याओं को जन्म दे सकता है सम्मिलित करने के लिए नहीं कर रहे हैं, तो उदाहरण के लिए एक नया डेवलपर इस बारे में भूल जाता है।

+0

उत्कृष्ट, धन्यवाद! प्रश्न हालांकि, ए) क्या यह लॉक पूरी तालिका के लिए होगा, या क्या मैं एक पंक्ति को लॉक कर सकता हूं? मैं नहीं चाहता कि सभी 2000 ग्राहकों को क्लाइंट एक्स से इस लॉक के लिए इंतजार करना पड़े, इससे पहले कि वे अधिक टिकट बना सकें (प्रति सेकेंड कॉन्सुरेंसी 2-3 टिकट की कल्पना करें), और बी) क्या होता है (और उचित वसूली क्या है पथ), यदि लॉक होने पर इस नंबर के लिए दूसरा कनेक्शन क्वेरी है? पुन: "लेनदेन को क्रमबद्ध करें" - यह पिछले प्रदर्शन लेनदेन को नए लोगों के सामने पूरा होने पर प्रदर्शन समस्या कैसे होगी। क्या यह एक बड़ी समस्या है? मेरे पास उच्च मात्रा होगी। – orokusaki

+2

@orokusaki: जैसा कि मैंने वर्णन किया है: केवल उस ग्राहक के लिए पंक्ति लॉक हो जाएगी। दूसरा कनेक्शन तब तक इंतजार करेगा जब तक कि पहली बार काम न करे। हां, इससे आपका प्रदर्शन कम हो जाएगा। लेकिन आप या तो इस तरह की संख्या (धीमी लेकिन सुरक्षित) प्राप्त कर सकते हैं या अनुक्रम का उपयोग करके उन्हें तेजी से प्राप्त कर सकते हैं लेकिन फिर वे सभी ग्राहकों के लिए अद्वितीय होंगे। आपको यह तय करना होगा कि क्या अधिक महत्वपूर्ण है –

2

आप प्रत्येक ग्राहक के लिए अनुक्रम बना सकते हैं और फिर कॉलम का मान nextval('name_of_the_sequence') पर सेट कर सकते हैं। यह वास्तव में serial काम करता है; आपके मामले में एकमात्र अंतर यह होगा कि आप कॉलम के लिए डिफ़ॉल्ट मान का उपयोग नहीं करते हैं और एक से अधिक अनुक्रम हैं।

एक नई पंक्ति डालने पर सही चयन करने वाले उन अनुक्रमों को बनाना एक पीएल/पीजीएसक्यूएल प्रक्रिया के माध्यम से अच्छी तरह से किया जा सकता है।

+0

ऐसा करने के लिए 2000 कॉलम की आवश्यकता के मुद्दे के अलावा, एक सीरियल फ़ील्ड का उपयोग करने में मौलिक समस्या यह है कि एक लुढ़का हुआ बैक ट्रांजैक्शन अभी भी उस नंबर का उपयोग करता है जो 'अगलीवाल' रिटर्न देता है, इसलिए यदि किसी दिए गए क्लाइंट के लिए टिकट नंबर 1001 हो सकते हैं, 1002, 1005, 1007, इत्यादि, वास्तविक अनुक्रम बनाए रखने बनाम (यानी, एक धारावाहिक कॉलम का मान कार्डिनिटी का सटीक उपाय नहीं है)। – orokusaki

+0

कृपया मेरा उत्तर पढ़ें। मैंने सीरियल कॉलम या विभिन्न कॉलम के बारे में बात नहीं की। आप अनुक्रमों को अलग से बना सकते हैं और 'अगलीवाल() ' – ThiefMaster

+0

@ थिफ़मास्टर का उपयोग करके उनसे मूल्य प्राप्त कर सकते हैं, क्या आप एक ट्रिगर (सम्मिलित ग्राहक) में अनुक्रम बनाने का सुझाव दे रहे हैं और फिर मूल्यों का चयन करने के लिए गतिशील एसक्यूएल की आवश्यकता है? (मैं एक पोस्टग्रेस नोब हूं, इसलिए मुझे यकीन नहीं है कि इनमें से कोई भी संभव है, लेकिन संभवतः ओपी को इस सामान को करने का एक स्वचालित तरीका चाहिए) –

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

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