2013-07-06 4 views
6

क्या किसी तालिका रिकॉर्ड के लिए किसी प्रकार का इन-ऑर्डर पहचानकर्ता उत्पन्न करने का कोई तरीका है?इन-ऑर्डर अनुक्रम पीढ़ी

मान लीजिए कि हमें दो धागे कर पूछना चाहते हैं:

थ्रेड 1:

begin; 
insert into table1(id, value) values (nextval('table1_seq'), 'hello'); 
commit; 

थ्रेड 2:

begin; 
insert into table1(id, value) values (nextval('table1_seq'), 'world'); 
commit; 

यह (समय के आधार पर) एक बाहरी पर्यवेक्षक होगा कि पूरी तरह से संभव है देखें (2, 'दुनिया') रिकॉर्ड (1, 'हैलो') से पहले दिखाई देता है।

यह ठीक है, लेकिन मैं 'table1' में सभी रिकॉर्ड्स प्राप्त करने का एक तरीका चाहता हूं जो पिछली बार बाहरी पर्यवेक्षक ने इसे चेक किया था।

तो, क्या उनके द्वारा डाले गए क्रम में रिकॉर्ड प्राप्त करने का कोई तरीका है? शायद ओआईडी मदद कर सकते हैं?

उत्तर

1

नहीं। चूंकि डेटाबेस तालिका में पंक्तियों का कोई प्राकृतिक क्रम नहीं है, आपको बस अपनी तालिका में मूल्यों के साथ काम करना है।

ठीक है, Postgres specific system columns cmin and ctid आप कुछ डिग्री के लिए दुरुपयोग कर सकते हैं।

टुपल आईडी (ctid) में फ़ाइल ब्लॉक संख्या और पंक्ति के लिए ब्लॉक में स्थिति शामिल है। तो यह डिस्क पर वर्तमान भौतिक क्रम का प्रतिनिधित्व करता है। बाद में जोड़े में ctid, सामान्यतः होगा। आपका SELECT कथन इस

SELECT *, ctid -- save ctid from last row in last_ctid 
FROM tbl 
WHERE ctid > last_ctid 
ORDER BY ctid 

ctid दिखाई दे सकता है डेटा प्रकार tid है। उदाहरण: '(0,9)'::tid

हालांकि यह है नहीं स्थिर के रूप में लंबे समय तक पहचानकर्ता, के बाद से VACUUM या किसी समवर्ती UPDATE या कुछ अन्य कार्यों के किसी भी समय एक टपल की भौतिक स्थिति बदल सकते हैं। लेनदेन की अवधि के लिए यह स्थिर है, हालांकि। और यदि आप अभी डालने वाले हैं और कुछ भी कुछ भी नहीं है, तो इसे आपके उद्देश्य के लिए स्थानीय रूप से काम करना चाहिए।

मैं serial स्तंभ के अलावा डिफ़ॉल्ट now() साथ एक टाइमस्टैम्प स्तंभ जोड़ना होगा ...

मैं भी एक स्तंभ डिफ़ॉल्ट अपने id स्तंभ (एक serial या IDENTITY स्तंभ) को पॉप्युलेट दिया जाएगा।यह अनुक्रम से संख्या को स्पष्ट रूप से लाने और उसके बाद डालने की तुलना में बाद के चरण में पुनर्प्राप्त करता है, जिससे दौड़ की स्थिति के लिए खिड़की को कम करना (लेकिन समाप्त नहीं करना) - कम से कम id को बाद में डाला जाएगा। विस्तृत निर्देश:

+0

मुझे नहीं लगता कि भौतिक पंक्ति स्थान पर भरोसा करना एक वैध रणनीति है। निरस्त लेनदेन, खो गया डेटाबेस कनेक्शन, आदि सभी बाद में पंक्ति को गलत क्रम में रखा जा सकता है। एक सीरियल कॉलम का उपयोग करना पर्याप्त नहीं है, क्योंकि पंक्ति डालने और थ्रेड 1 लेनदेन करने के बीच कोई देरी हो सकती है, जो थ्रेड 2 लेनदेन को प्रतिबद्ध और उसके सामने देखा जा सकता है। – Tometzky

+0

@Tometzky: मैं मानता हूं कि यह विश्वसनीय नहीं है। मैंने पहले से ही उल्लेख किए जाने से भी अधिक कारणों के लिए। इसमें केवल ऑर्डर टुपल्स के लिए * कुछ * कारण शामिल हैं (जैसे अनुक्रम से अलग-अलग आईडी प्राप्त करना), लेकिन दूसरों को नहीं। –

+0

मैंने सीटीआईडी ​​का दुरुपयोग करने की कोशिश की लेकिन यह काम नहीं किया क्योंकि मैं समय-समय पर कुछ पंक्तियां हटाना चाहता हूं। एक स्वचालित monotonically बढ़ते काउंटर होने के लिए अच्छा होगा, लेकिन मुझे लगता है कि मुझे स्पष्ट लॉकिंग करना होगा। – Cyberax

1

यदि आप मतलब है कि यह भी hello पंक्ति को देखने के लिए है, प्रत्येक क्वेरी अगर यह world पंक्ति देखता है तो आपको बस इतना करना चाहते हैं:

begin; 
lock table table1 in share update exclusive mode; 
insert into table1(id, value) values (nextval('table1_seq'), 'hello'); 
commit; 

यह share update exclusive mode सबसे कमजोर लॉक मोड जो स्वयं को विशिष्ट है - केवल एक सत्र इसे एक समय में पकड़ सकता है।

ध्यान रखें कि इससे यह अनुक्रम अंतर कम नहीं होगा - यह एक अलग मुद्दा है।

3

क्या आप चाहते हैं उसी क्रम कि वे आवेषण किया में प्रतिबद्ध करने के लिए (उनके आवेषण दृश्यमान बनाकर) लेनदेन के लिए मजबूर किया जा सके। जहां तक ​​अन्य ग्राहक चिंतित हैं तब तक नहीं हुआ जब तक वे प्रतिबद्ध नहीं होते हैं, क्योंकि वे वापस रोल और गायब हो सकते हैं।

यह बात तब भी आप एक स्पष्ट begin/commit में आवेषण लपेट नहीं है। लेनदेन प्रतिबद्धता, भले ही पूर्ण रूप से किया गया हो, फिर भी उसी क्रम में जरूरी नहीं है कि पंक्ति स्वयं को डाली गई हो। यह ऑपरेटिंग सिस्टम सीपीयू शेड्यूलर ऑर्डरिंग फैसलों, आदि के अधीन है

भले ही पोस्टग्रेएसक्यूएल गंदा पढ़ता है, यह अभी भी सत्य होगा। सिर्फ इसलिए कि आप किसी दिए गए क्रम में तीन प्रविष्टियों का मतलब यह नहीं है कि वे उस क्रम में समाप्त करेंगे।

ऐसा करने के लिए कोई आसान या विश्वसनीय तरीका नहीं है जो आप चाहते हैं कि समेकन को संरक्षित रखे। आपको एक ही कार्यकर्ता के क्रम में अपने आवेषण करने की आवश्यकता होगी - या टेमेट्स्की के रूप में टेबल लॉकिंग का उपयोग करें, जो मूल रूप से वही प्रभाव डालता है क्योंकि आपके किसी भी डालने वाले थ्रेड किसी भी समय कुछ भी कर सकते हैं।

आप सलाहकार लॉकिंग का उपयोग कर सकते हैं, लेकिन प्रभाव वही है।

एक टाइमस्टैम्प का उपयोग में मदद नहीं करेगा, जब से तुम पता नहीं करते दो है जो अभी तक प्रतिबद्ध नहीं किया गया के बीच एक टाइमस्टैम्प के साथ एक पंक्ति वहाँ किसी भी दो timestamps के लिए है।

आप पहचान कॉलम पर भरोसा नहीं कर सकते हैं जहां आप केवल "अंतराल" तक पंक्तियां पढ़ते हैं क्योंकि रोलबैक के कारण सिस्टम-जेनरेट किए गए कॉलम में अंतर सामान्य होते हैं।

मुझे लगता है कि आपको वापस कदम उठाना चाहिए और क्यों देखें आपके पास यह आवश्यकता है और, यह आवश्यकता दी गई है, आप व्यक्तिगत समवर्ती आवेषण का उपयोग क्यों कर रहे हैं।

शायद आप एक ही सत्र से छोटे-छोटे बैच किए गए आवेषण करने से बेहतर होंगे?

+0

मुझे एक समान चुनौती का सामना करना पड़ रहा है और ऐसा करने का मेरा कारण घटनाओं की एक फ़ीड का पर्दाफाश करना है। प्रत्येक पंक्ति प्रतिनिधित्व और घटना। फ़ीड का अनुबंध होना चाहिए कि पेज अपरिवर्तनीय हैं। ग्राहक अनुरोध पृष्ठ को 'पृष्ठ' के रूप में करेंगे = और सीमा = XX' के बाद। हालांकि आदेश से बाहर आवेषण 'पृष्ठ' के बाद = 3' लौटने के बाद '[5]' पहली बार और '4,5]' 4 "के बाद किया जा सकता है। यह केवल एक सारणी है इसलिए यह फ़ीड के लिए एक अच्छा आधार लग रहा था। लेकिन आदेश से बाहर दिखाई देने वाले सीरियल नंबरों के साथ मैं सोच रहा हूं कि कोई बेहतर तरीका है। हम वर्तमान में नई प्रविष्टियों की जांच के लिए कई पृष्ठों को देख रहे हैं। –

+1

यह वही है जो तार्किक डिकोडिंग के लिए है। Wal2json, pglogical, आदि में देखो। –

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