2013-03-13 7 views
5

मैं एक संग्रहीत प्रक्रिया है कि मूल्यों मेरी अस्थायी तालिका का चयन करता है और उन्हें इतना की तरह डेटाबेस में सम्मिलित करता चल रहा हूँ:INSERT INTO .. ​​का चयन करें .. अद्वितीय बाधा उल्लंघन

INSERT INTO emails (EmailAddress) (
    SELECT 
     DISTINCT eit.EmailAddress 
    FROM #EmailInfoTemp eit 
     LEFT JOIN emails ea 
     ON eit.EmailAddress = ea.EmailAddress 
    WHERE ea.EmailAddressID IS NULL ) 

दुर्लभ मामलों पर (~ एक बार हर दो एक सर्वर पर घंटों का जो हजारों अनुरोधों को एक मिनट में संभालता है), तो मुझे ईमेल एड्रेस कॉलम पर एक इंडेक्स पर एक अद्वितीय बाधा त्रुटि "अद्वितीय कुंजी बाधा का उल्लंघन" प्राप्त होता है।

मैं पुष्टि कर सकता हूं कि मैं डुप्लिकेट मानों में गुजर रहा हूं। यहां तक ​​कि अगर मैं था, तो इसे DISTINCT द्वारा पकड़ा जाना चाहिए।

-SQL सर्वर 2008 -Stored proc + लेनदेन का उपयोग नहीं कर + JDBC callablestatement

यह हो सकता है कि चयन करें और आगामी सम्मिलित करें के बीच, वहाँ एक ही/अलग संग्रहीत proc कि एक सम्मिलित पूरा करने के लिए एक और फोन था समान डेटा के साथ? यदि हां, तो इसे रोकने का सबसे अच्छा तरीका क्या होगा?

कुछ विचार: हमारे पास "क्लाइंट" के कई डुप्लिकेट उदाहरण हैं जो इस SQL ​​सर्वर के साथ एक बार उत्पादन में संवाद करते हैं, इसलिए मेरी पहली प्रतिक्रिया एक सहमति थी, लेकिन मैं इसे खुद को दोहराना प्रतीत नहीं कर सकता। यह मेरा सबसे अच्छा अनुमान था, लेकिन यह अब तक कहीं नहीं चला गया है। यह हमारे स्टेजिंग पर्यावरण पर नहीं होता है जहां लोड उत्पादन उत्पादन की तुलना में महत्वहीन है। यह मुख्य कारण था कि मैंने समेकन मुद्दों को देखना शुरू कर दिया।

+1

दोनों पक्षों पर ईमेल एड्रेस में कुल मूल्य अद्वितीय कुंजी बाधा का उल्लंघन कर सकता है। यदि यह कॉलम निरर्थक है तो आप 'मौजूद नहीं' के रूप में सम्मिलन को फिर से लिख सकते हैं। –

+0

अच्छा बिंदु। मैं कोड में नल के खिलाफ जांच करता हूं, लेकिन मुझे लगता है कि मैं इसे एसक्यूएल में फिर से देख सकता हूं। –

उत्तर

5

त्रुटि शायद एक ही समय में एक सम्मिलन निष्पादित करने वाले दो सत्रों के कारण होती है।

आप MERGE का उपयोग करके अपना SQL कोड सुरक्षित बना सकते हैं। जैसा कि हारून बर्ट्रैंड की टिप्पणी कहती है (धन्यवाद!), you have to include a with (holdlock) hint to make merge really safe

; merge emails e with (holdlock) 
using #EmailInfoTemp eit 
on  e.EmailAddress = eit.EmailAddress 
when not matched then insert 
     (EmailAddress) values (eit.EmailAddress) 

merge बयान उचित ताले लेने के लिए सुनिश्चित करें कि कोई अन्य सत्र में चुपके कर सकते हैं के बीच यह है "नहीं मिलान किया" की जाँच करें और "सम्मिलित" होगा।

यदि आप merge का उपयोग नहीं कर सकते हैं, तो आप समस्या को हल कर सकते हैं। सुनिश्चित करें कि एक ही समय में कोई भी दो आवेषण नहीं चल रहे हैं। यह आमतौर पर mutex या अन्य सिंक्रनाइज़ेशन निर्माण के साथ करना आसान है।

+1

['MERGE' तब तक सुरक्षित नहीं है जब तक कि आप' होल्डॉक 'संकेत जोड़ते हैं] (http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx)। –

+0

@AaronBertrand: धन्यवाद। एमईआरजीई के लिए एमएसडीएन पेज का कहना है, "जब तक मिलान नहीं किया जाता है तब से रीडपैस्ट निर्दिष्ट करना [तब तक] INSERT के परिणामस्वरूप INSERT संचालन हो सकता है जो अद्वितीय बाधाओं का उल्लंघन करता है।" इसलिए मैंने माना कि यह तब तक सुरक्षित था जब तक आप 'readpast' निर्दिष्ट नहीं करते। – Andomar

+1

हाँ माइक्रोसॉफ्ट आमतौर पर उन सभी मामलों को दस्तावेज करने की संभावना नहीं है जहां यह टूट सकता है। प्रलेखन [इनमें से किसी भी अभी तक हल की गई बग्स (नीचे स्क्रॉल) के बारे में बात नहीं करता है] (http://www.sqlperformance.com/2013/02/t-sql-queries/another- विलय-बग)। :-) –

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