IF NOT EXISTS
. के क्रियान्वयन में यह थोड़ा सा मस्सा है टेबल और स्कीमा के लिए। मूल रूप से, वे एक जोरदार प्रयास कर रहे हैं, और PostgreSQL दौड़ की स्थिति को सफाई से नहीं संभालता है। यह सुरक्षित है, लेकिन बदसूरत है।
यदि स्कीमा किसी अन्य सत्र में समवर्ती रूप से बनाई जा रही है लेकिन अभी तक प्रतिबद्ध नहीं है, तो यह दोनों मौजूद है और मौजूद नहीं है, इस पर निर्भर करता है कि आप कौन हैं और आप कैसे दिखते हैं। अन्य लेन-देन के लिए सिस्टम कैटलॉग में नई स्कीमा को "देखना" संभव नहीं है क्योंकि यह प्रतिबद्ध नहीं है, इसलिए यह pg_namespace
में प्रविष्टि है अन्य लेनदेन के लिए दृश्यमान नहीं है। तो CREATE SCHEMA
/ CREATE TABLE
इसे बनाने की कोशिश करता है, क्योंकि जहां तक इसका संबंध है, वस्तु मौजूद नहीं है।
हालांकि, यह एक अद्वितीय बाधा वाली तालिका में एक पंक्ति डालता है। कार्य करने के लिए अद्वितीय बाधाओं को अप्रतिबद्ध पंक्तियों को देखने में सक्षम होना चाहिए। तो CREATE
. करने वाले पहले लेन-देन तक इन्सर्ट ब्लॉक (रुक जाता है) या तो करता है या वापस रोल करता है। यदि यह प्रतिबद्ध है, तो दूसरा लेन-देन बंद हो जाता है, क्योंकि यह एक ऐसी पंक्ति डालने का प्रयास करता है जो एक अद्वितीय बाधा का उल्लंघन करता है। CREATE SCHEMA
इस मामले को पकड़ने और पुनः प्रयास करने के लिए पर्याप्त स्मार्ट नहीं है।
इस PostgreSQL को ठीक से ठीक करने के लिए शायद विधेय लॉकिंग की आवश्यकता होगी, जहां यह पंक्ति की क्षमता को लॉक कर सकता है . इसे UPSERT
. को लागू करने के लिए चल रहे वर्तमान कार्य के हिस्से के रूप में जोड़ा जा सकता है ।
इन विशेष आदेशों के लिए, PostgreSQL शायद एक गंदा पढ़ा कर सकता है सिस्टम कैटलॉग में, जहां यह अप्रतिबद्ध परिवर्तन देख सकता है। फिर यह अनकम्फर्टेबल ट्रांजैक्शन के कमिट या रोल बैक होने का इंतजार कर सकता है, यह देखने के लिए कि कोई और इंतजार कर रहा है या नहीं, फिर से डर्टी रीड करें और फिर से प्रयास करें। लेकिन इसमें एक दौड़ की स्थिति होगी जहां कोई और स्कीमा बना सकता है जब आप इसे पढ़ने के लिए पढ़ते हैं और जब आप इसे बनाने का प्रयास करते हैं।
तो IF NOT EXISTS
वेरिएंट को यह करना होगा:
- यह देखने के लिए जांचें कि क्या स्कीमा मौजूद है; अगर ऐसा होता है, तो बिना कुछ किए समाप्त करें।
- तालिका बनाने का प्रयास
- यदि अद्वितीय बाधा त्रुटि के कारण निर्माण विफल हो जाता है, तो प्रारंभ में पुनः प्रयास करें
- यदि तालिका बनाना सफल होता है, तो समाप्त करें
जहां तक मुझे पता है कि किसी ने इसे लागू नहीं किया है, या उन्होंने कोशिश की और इसे स्वीकार नहीं किया गया। इस दृष्टिकोण के साथ, लेन-देन आईडी बर्न रेट आदि के साथ संभावित समस्याएं हो सकती हैं।
मुझे लगता है कि यह एक प्रकार का बग है, लेकिन यह "हाँ, हम जानते हैं" एक प्रकार का बग है, न कि "हम उस तरह की बग को ठीक करने पर सही होंगे"। इसके बारे में pgsql-bugs पर बेझिझक पोस्ट करें; कम से कम दस्तावेज़ में IF NOT EXISTS
. के बारे में इस चेतावनी का उल्लेख होना चाहिए ।
मैं डीडीएल को एक साथ इस तरह करने की अनुशंसा नहीं करता।