Postgres, पहले से उपयोग किए गए PK मान को क्यों उत्पन्न करता है?


22

मैं Django का उपयोग कर रहा हूं, और हर बार एक बार मुझे यह त्रुटि मिलती है:

अखंडता: डुप्लिकेट कुंजी मान अद्वितीय बाधा का उल्लंघन करता है "myapp_mymodel_pkey"
विवरण: कुंजी (आईडी) = (1) पहले से मौजूद है।

मेरा पोस्टग्रेज डेटाबेस वास्तव में 1 की प्राथमिक कुंजी के साथ एक myapp_mymodel ऑब्जेक्ट है।

Postgres उस प्राथमिक कुंजी को फिर से उपयोग करने का प्रयास क्यों करेगा? या, क्या यह मेरे आवेदन (या Django के ORM) के लिए सबसे अधिक संभावना है?

यह समस्या अभी अभी लगातार 3 बार हुई है। मैंने पाया है कि जब यह होता है तो यह किसी दिए गए टेबल के लिए एक या एक से अधिक बार होता है, फिर नहीं। ऐसा लगता है कि हर तालिका के लिए ऐसा होता है जब यह पूरी तरह से दिनों के लिए बंद हो जाता है, ऐसा होने पर कम से कम एक मिनट या प्रति तालिका के लिए हो रहा है, और केवल रुक-रुक कर हो रहा है (सभी तालिकाएं अभी नहीं)।

तथ्य यह है कि यह त्रुटि बहुत रुक-रुक कर है (केवल 3 या 2 सप्ताह में इतनी बार हुई है - DB पर कोई अन्य भार नहीं है, बस मुझे अपने आवेदन का परीक्षण करना है) जो मुझे निम्न स्तर की समस्या से इतना सावधान करता है।


Django विशेष रूप से बताता है कि प्राथमिक कुंजी DBMS द्वारा निर्दिष्ट की जाती है - जब तक कि निर्दिष्ट नहीं किया जाता है - अब, मुझे नहीं पता कि @orokusaky अपने अजगर कोड में क्या कर रहा था, लेकिन मैं इस पृष्ठ पर समाप्त हुआ क्योंकि मुझे पूरा विश्वास है कि मेरे पास कोई कोड नहीं है एक विशिष्ट प्राथमिक कुंजी का उपयोग करने की कोशिश कर रहा हूं और मैंने कभी भी एक डीबीएमएस को गलत उपयोग करने की कोशिश नहीं की है।
MCCC

जवाबों:


34

PostgreSQL अपने दम पर डुप्लिकेट मान डालने की कोशिश नहीं करेगा, यह आप (आपका आवेदन, ओआरएम शामिल) जो करता है।

यह या तो पीके को दिए गए मानों को गलत स्थिति में सेट करने के लिए एक अनुक्रम हो सकता है और तालिका में पहले से ही इसके मूल्य के बराबर मूल्य है nextval()- या बस यह कि आपका आवेदन गलत काम करता है। पहले वाले को ठीक करना आसान है:

SELECT setval('your_sequence_name', (SELECT max(id) FROM your_table));

दूसरे का मतलब डिबगिंग है।

Django (या किसी भी अन्य लोकप्रिय ढांचे) अपने दम पर दृश्यों को रीसेट नहीं करता है - अन्यथा हम हर दूसरे दिन ऐसे ही सवाल करेंगे।


क्या यह अलग-थलग स्तरों के बारे में ध्यान देने योग्य है (@ andi के जवाब पर आधारित)? उदाहरण के लिए, यदि पहला पूरा होने से पहले दूसरी क्वेरी आती है, तो क्या यह संभव है, एक ऐसा परिदृश्य दिया जाए जहां मैं लेनदेन का उपयोग नहीं कर रहा हूं, एक रिकॉर्ड डालें जो प्राप्त करने में परिणाम करता हैmax(id) , जिसके परिणामस्वरूप पहली क्वेरी पूरी से पहले , और फिर दोनों में परिणाम होता है एक ही परिणाम?
orokusaki

7

आपके लिए एक तालिका में एक पंक्ति सम्मिलित करने के लिए सबसे अधिक संभावना है, जिसके लिए धारावाहिक स्तंभ अनुक्रम मान अपडेट नहीं किया गया है।

अपनी तालिका में निम्नलिखित कॉलम पर विचार करें जो पोस्टग्रो के लिए Django ORM द्वारा परिभाषित प्राथमिक कुंजी है

id serial NOT NULL

जिसका डिफ़ॉल्ट मान निर्धारित है

nextval('table_name_id_seq'::regclass)

अनुक्रम का मूल्यांकन केवल तब किया जाता है जब आईडी फ़ील्ड को रिक्त के रूप में सेट किया जाता है। लेकिन यह समस्या है अगर पहले से ही तालिका में प्रविष्टियां हैं।

सवाल यह है कि पहले की प्रविष्टियों ने अनुक्रम अद्यतन को ट्रिगर क्यों नहीं किया? ऐसा इसलिए है क्योंकि आईडी मूल्य स्पष्ट रूप से पहले की सभी प्रविष्टियों के लिए प्रदान किया गया था।

मेरे मामले में उन प्रारंभिक प्रविष्टियों को जुड़ाव से पलायन के माध्यम से लोड किया गया था।

यह समस्या यादृच्छिक PK मान के साथ कस्टम प्रविष्टियों के माध्यम से भी मुश्किल हो सकती है।

उदाहरण के लिए कहें। आपकी तालिका में 10 प्रविष्टियाँ हैं। आप PK = 15 के साथ एक स्पष्ट प्रविष्टि करें। कोड के माध्यम से अगले चार आवेषण पूरी तरह से ठीक काम करेंगे लेकिन 5 वें एक अपवाद को उठाएंगे।

DETAIL: Key (id)=(15) already exists.

इस पोस्ट के लिए आपका धन्यवाद। मैं लंबे समय से इस तरह के मामले पर बहस कर रहा हूं। बहुत कम ही ऐसा हुआ। यह पता चला है कि एक विशिष्ट "मैनुअल" एडमिन फ़ंक्शन एक पुराने मूल्य के साथ पहचान काउंटर छोड़कर, अपने आप ही आईडी डाल सकता है। यह "जेनरेट बाय डिफाइन्ड एएस IDENTITY" के साथ एक वास्तविक संकट है। अगली बार जब मैं किसी पहचान स्तंभ को परिभाषित करता हूं, तो "ALWAYS" के बजाय "BY DEFAULT" का उपयोग करने से पहले दो बार सोचूंगा।
माइकल

4

मैं बहुत ही त्रुटि के साथ यहां समाप्त हुआ, जो शायद ही कभी हो रहा था, और ट्रैक करने के लिए कठिन था, क्योंकि मैं इसे ढूंढ रहा था जहां मुझे नहीं करना चाहिए।

दोष JS दोहराव था जो दो बार सर्वर पर POST कर रहा था! इसलिए कभी-कभी यह न केवल आपके django (या किसी अन्य वेब फ्रेमवर्क) के विचारों और रूपों पर एक नज़र रखने के लायक है, बल्कि बहुत आगे की तरफ भी होता है।


1

हाँ अजीब बात है। माइग्रेशन में डेटा लोड करने के दौरान गलत होने पर मेरे मामले में स्पष्ट रूप से कुछ। मैंने खाली माइग्रेशन जोड़ा और कुछ प्रारंभिक डेटा जोड़ने के लिए लाइनें लिखीं, मेरे मामले में 6 रिकॉर्ड

db_alias = schema_editor.connection.alias
bulk = []
for item in items:
    bulk.append(MyModel(
        id=item[0],
        value=item[1],
        slug=item[2],
        name=item[3],
    ))

MyModel.objects.using(db_alias).bulk_create(bulk)

फिर व्यवस्थापक पैनल में मैंने नया आइटम जोड़ने का प्रयास किया और मिला:

पहली कोशिश:

DETAIL:  Key (id)=(1) already exists.

बाद के प्रयास:

DETAIL:  Key (id)=(2) already exists.
DETAIL:  Key (id)=(3) already exists.
DETAIL:  Key (id)=(4) already exists.
DETAIL:  Key (id)=(5) already exists.
DETAIL:  Key (id)=(6) already exists.

और अंत में 7 वें और समय पर सभी सफल होते हैं

इसलिए मैं कह रहा हूं कि शायद थोक_संरचना से संबंधित कोई चीज है क्योंकि मैंने वहां 6 आइटम लोड किए हैं। यह शायद अपने Django परियोजना में ऐसा ही कुछ कारण हो सकता है।

Django 1.9 PostgreSQL 9.3.14

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.