2009-03-30 31 views
5

के पीके को बढ़ाने के लिए डेटाबेस रेस स्थिति से कैसे बचें मेरे पास SQL ​​सर्वर 2005 में एक विरासत डेटा तालिका है जिसमें कोई पहचान/ऑटोइनक्रिकमेंट वाला पीके है और इसे लागू करने की कोई शक्ति नहीं है।मैन्युअल रूप से नई पंक्ति

नतीजतन, मुझे ओएसई के माध्यम से मैन्युअल रूप से एएसपी.NET में नए रिकॉर्ड बनाने के लिए मजबूर होना पड़ता है "तालिका से चयन करें (आईडी) + 1 तालिका से पहले- -इंटर तकनीक डालें।

स्पष्ट रूप से यह एक साथ आवेषण की स्थिति में आईडी पर दौड़ की स्थिति बनाता है।

रेस टकराव की घटना को गहन तरीके से हल करने का सबसे अच्छा तरीका क्या है? मैं टकराव का पता लगाने की लाइनों के साथ वीबी.नेट या सी # कोड विचारों की तलाश में हूं और फिर एक और अधिकतम (आईडी) + प्राप्त करके असफल डालने का पुनः प्रयास कर रहा हूं। 1. क्या यह किया जा सकता है?

विचार? टिप्पणियाँ? बुद्धिमत्ता?

धन्यवाद!

नोट: यदि मैं किसी भी तरह से डेटाबेस को नहीं बदल सकता तो क्या होगा?

उत्तर

4

डेटाबेस स्कीमा को बदलने में सक्षम नहीं है कठोर है।

यदि आप तालिका में मौजूदा पीके डालते हैं तो आपको पीके बाधा उल्लंघन का संकेत देने वाले संदेश के साथ एसक्लएक्सप्शन प्राप्त होगा। इस अपवाद को पकड़ें और फिर से प्रयास करें जब तक आप सफल न हों। यदि आपको लगता है कि टक्कर दर बहुत अधिक है, तो आप max(id) + 1 के बजाय max(id) + <small-random-int> आज़मा सकते हैं। ध्यान दें कि इस दृष्टिकोण के साथ आपके आईडी में अंतराल होगा और आईडी स्थान जल्द ही समाप्त हो जाएगा।

एक और संभावित दृष्टिकोण डेटाबेस के बाहर autoincrementing आईडी अनुकरण करना है। उदाहरण के लिए, एक स्थिर पूर्णांक, Interlocked.Increment बनाएं जब भी आपको अगली आईडी की आवश्यकता हो और लौटा मूल्य का उपयोग करें। मुश्किल हिस्सा इस स्थिर काउंटर को अच्छे मूल्य में शुरू करना है। मैं Interlocked.CompareExchange साथ यह करना होगा: केवल

class Autoincrement { 
    static int id = -1; 
    public static int NextId() { 
    if (id == -1) { 
     // not initialized - initialize 
     int lastId = <select max(id) from db> 
     Interlocked.CompareExchange(id, -1, lastId); 
    } 
    // get next id atomically 
    return Interlocked.Increment(id); 
    } 
} 

जाहिर बाद काम करता है अगर सब डाला आईडी एकल प्रक्रिया के Autoincrement.NextId के माध्यम से प्राप्त कर रहे हैं।

+0

में ग्राहक पक्ष लेनदेन की अनुमति है बस मुझे धन्यवाद चाहिए !!! –

6

पहचान कॉलम के साथ एक सहायक तालिका बनाएं। ऑक्स तालिका में लेनदेन डालने में, मान प्राप्त करें और अपनी विरासत तालिका में डालने के लिए इसका उपयोग करें। इस बिंदु पर आप ऑक्स तालिका में डाली गई पंक्ति को भी हटा सकते हैं, बिंदु केवल इसे बढ़ी हुई मानों के स्रोत के रूप में उपयोग करने के लिए है।

+0

यह लागू करने के लिए बहुत आसान है, +1 –

+0

बहुत चालाक, धन्यवाद! दुर्भाग्यवश मेरे पास डेटाबेस बदलने का कोई तरीका नहीं है। यह जमा हुआ है। –

+0

इसे दूसरे, लिंक किए गए डेटाबेस के रूप में जोड़ें - या एक ही चीज़ को प्राप्त करने के लिए कोड में स्थानीय फ़ाइल का उपयोग करें। –

1

डेटाबेस को बदलने का सबसे अच्छा समाधान है। आप कॉलम को पहचान कॉलम के रूप में बदलने में सक्षम नहीं हो सकते हैं, लेकिन आपको यह सुनिश्चित करने में सक्षम होना चाहिए कि कॉलम पर एक अनोखी बाधा है और अपने मौजूदा पीके के साथ बीजित एक नया पहचान कॉलम जोड़ें। फिर या तो नए कॉलम का उपयोग करें या पुराना कॉलम नया या दो दोनों बनाने के लिए ट्रिगर का उपयोग करें।

3

कुंजी एक कथन या एक लेनदेन में करना है।

क्या आप यह कर सकते हैं?

INSERT (PKcol, col2, col3, ...) 
SELECT (SELECT MAX(id) + 1 FROM table WITH (HOLDLOCK, UPDLOCK)), @val2, @val3, ... 

परीक्षण के बिना, यह शायद भी काम करेगा:

INSERT (PKcol, col2, col3, ...) 
VALUES ((SELECT MAX(id) + 1 FROM table WITH (HOLDLOCK, UPDLOCK)), @val2, @val3, ...) 

आप नहीं कर सकते हैं, तो एक और तरीका है एक ट्रिगर में यह करने के लिए है।

  1. ट्रिगर सम्मिलित करें लेन-देन
  2. उपयोग HOLDLOCK, मैक्स के लिए UPDLOCK का हिस्सा है। यह पंक्ति ताला रखती है जब तक प्रतिबद्ध
  3. पंक्ति अवधि

एक दूसरा डालने पहले कम्प्लिट्स जब तक इंतजार करेंगे के लिए लॉक किया गया है अपडेट किया जा रहा। नकारात्मकता यह है कि आप प्राथमिक कुंजी बदल रहे हैं।

एक सहायक तालिका को लेनदेन का हिस्सा होना चाहिए।

या के रूप में सुझाव स्कीमा बदल ...

+0

मैंने एक नेस्टेड डालने की कोशिश की और उसने मुझे बताया कि मैं नेस्टेड आवेषण नहीं कर सकता। मेरे पास SQL ​​अपडेट/इन्सर्ट के अलावा किसी भी तरह से डेटाबेस को बदलने की कोई शक्ति नहीं है। –

+0

क्या आपके क्लाइंट कोड – gbn

2

क्या serializable लेनदेन में पूरे बैच (आईडी के लिए चुन सकते हैं और सम्मिलित) चलाने के बारे में?

आपको डेटाबेस में बदलाव करने की आवश्यकता होनी चाहिए।

3

नोट: आपको केवल हमेशा बढ़ते पूर्णांक का स्रोत होना चाहिए। यह एक ही डेटाबेस से, या यहां तक ​​कि डेटाबेस से भी नहीं आना है।

व्यक्तिगत रूप से, मैं SQL Express का उपयोग करता हूं क्योंकि यह मुफ़्त और आसान है।

आप एक वेब सर्वर है, तो: एक एकल तालिका [आईडी] एक भी autoincrementing क्षेत्र [NEW_ID] के साथ साथ वेब सर्वर पर किसी SQL एक्सप्रेस डेटाबेस बनाएँ। इस [ids] तालिका में एक रिकॉर्ड डालें, [new_id] प्राप्त करें, और तालिका में पीके के रूप में अपनी डेटाबेस परत पर पास करें।

आप एक से अधिक वेब सर्वर है, तो: यह सेटअप करने के लिए एक दर्द है, लेकिन आप उचित बीज/वेतन वृद्धि की स्थापना (यानी वेतन वृद्धि = 3, और बीज = 1/2/3 तीन वेब के लिए द्वारा एक ही चाल का उपयोग कर सकते सर्वर)।

1

मुख्य चिंता समवर्ती पहुंच है? मेरा मतलब है, क्या आपके ऐप के कई उदाहरण होंगे (या, भगवान forbid, आपके नियंत्रण के बाहर अन्य ऐप्स) एक साथ सम्मिलित प्रदर्शन कर रहे हैं?

यदि नहीं, तो आप शायद अपने ऐप में एक केंद्रीय, सिंक्रनाइज़ मॉड्यूल के माध्यम से आवेषण प्रबंधित कर सकते हैं, और पूरी तरह से दौड़ की स्थिति से बच सकते हैं।

यदि ऐसा है, तो ... जोएल ने कहा, डेटाबेस बदलें। मुझे पता है कि आप नहीं कर सकते हैं, लेकिन समस्या पहाड़ियों की तरह पुरानी है, और इसे डेटाबेस स्तर पर अच्छी तरह से हल किया गया है। यदि आप इसे स्वयं ठीक करना चाहते हैं, तो आपको बस बार-बार लूप करना होगा (सम्मिलित करें, टक्कर के लिए जांचें, हटाएं) बार-बार। मौलिक समस्या यह है कि आप एक लेनदेन नहीं कर सकते (मेरा मतलब यह नहीं है कि SQL "ट्रांज़ेक्शन" अर्थ में, लेकिन बड़े डेटा-सिद्धांत अर्थ में) यदि आपके पास डेटाबेस से समर्थन नहीं है।

मेरे पास एकमात्र और विचार है कि यदि आपके पास कम से कम इस पर नियंत्रण है कि किसके पास डेटाबेस तक पहुंच है (उदाहरण के लिए, केवल "अधिकृत" ऐप्स, या तो आपके द्वारा लिखित या अनुमोदित), आप एक साइड-बैंड म्यूटेक्स को कार्यान्वित कर सकते हैं प्रकार के, जहां म्यूटक्स के सभी ऐप्स और स्वामित्व द्वारा "टॉकिंग स्टिक" साझा किया जाता है, उसे सम्मिलित करने की आवश्यकता होती है। यह मोम की अपनी बालों वाली गेंद होगी, हालांकि, आपको मृत ग्राहकों के लिए नीति का पता लगाना होगा, जहां यह होस्ट किया गया है, कॉन्फ़िगरेशन समस्याएं इत्यादि हैं और निश्चित रूप से एक "दुष्ट" ग्राहक बात करने वाली छड़ी के बिना आवेषण कर सकता है और पूरे सेटअप नली।

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