SQL सर्वर डेटाबेस में पहचान वृद्धि बढ़ रही है


126

FeeSQL Server 2012 डेटाबेस पहचान वृद्धि में कॉलम "ReceiptNo" में मेरी एक तालिका में निम्नलिखित दो चीजों के आधार पर अचानक 1 के बजाय 100s पर कूदना शुरू हो गया।

  1. अगर यह 1205446 है, तो यह 1206306 हो जाता है, अगर यह 1206321 है, तो यह 1207306 हो जाता है और अगर यह 1207314 है, तो यह 1208306 हो जाता है। मैं आपको यह नोट करना चाहता हूं कि अंतिम तीन अंक स्थिर रहें या 306 जब भी कूदें निम्न चित्र में दिखाया गया है।

  2. यह समस्या तब होती है जब मैं अपने कंप्यूटर को पुनरारंभ करता हूं

यहाँ छवि विवरण दर्ज करें


यदि आप order by ReceiptNoअपनी क्वेरी में जोड़ते हैं तो क्या वे रिकॉर्ड वास्तव में नहीं हैं? क्या आप सुनिश्चित हैं कि जब रिकॉर्ड डाले जा रहे हैं तो कोई त्रुटि नहीं है? यदि कोई रिकॉर्ड सम्मिलित करने का प्रयास करता है और पहचान विफल हो जाती है, तो रिकॉर्ड हटाए जाने पर एक ही बात। यदि रिकॉर्ड हटा दिए जाते हैं तो ReceiptNoरीसेट नहीं होता है। क्या आप तालिका के लिए तालिका बना सकते हैं Fee?
टैरिन

4
पहला सवाल है - यह क्यों मायने रखता है? यह एक अनूठे यूनिक आईडी होना चाहिए
एंड्रयू

1
क्या यह एक सर्वर पर चल रहा है या यह शायद डेस्कटॉप पर व्यक्त होता है? आश्चर्य है कि ऐसा क्यों लगता है कि सेवा को इतनी बार फिर से शुरू किया गया है?
मार्टिन स्मिथ

@bluefeet मुझे पता है कि जब त्रुटि होती है, तो पहचान वृद्धि होती है। मुझे यकीन है कि कोई त्रुटि नहीं है। Im तालिका और पंक्तियों को सम्मिलित करने के लिए उपयोग की जाने वाली संग्रहीत कार्यविधि को जोड़कर मेरे प्रश्न का संपादन करता है।
काशिफ

@ आकाश - 99% यकीन है कि जरूरत नहीं है। वास्तव में 1000 से कूदता है ( 1206306, 1207306, 1207806) का अर्थ है कनेक्ट आइटम थ्रेड में स्पष्टीकरण लगभग निश्चित रूप से लागू होता है।
मार्टिन स्मिथ

जवाबों:


158

SQL सर्वर 2012 के बाद से प्रदर्शन में सुधार के कारण आप इस व्यवहार का सामना कर रहे हैं।

अब यह डिफ़ॉल्ट रूप से IDENTITYएक intकॉलम के लिए मूल्यों का आवंटन करते समय 1,000 के कैश आकार का उपयोग करता है और सेवा को पुन: उपयोग नहीं किया गया अप्रयुक्त मानों को खो सकता है (कैश आकार bigint/ के लिए 10,000 है numeric)।

यह प्रलेखन में उल्लेख किया गया है

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

आपके द्वारा दिखाए गए डेटा से ऐसा लगता है कि यह 22 दिसंबर के लिए डेटा प्रविष्टि के बाद हुआ था, जब इसे फिर से शुरू किया गया SQL सर्वर ने मान आरक्षित किए थे 1206306 - 1207305। 24 - 25 दिसंबर के लिए डेटा प्रविष्टि के बाद एक और पुनरारंभ किया गया और SQL सर्वर 1207306 - 1208305ने 28 वीं के लिए प्रविष्टियों में दिखाई देने वाली अगली श्रेणी को आरक्षित कर दिया ।

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

यदि यह किसी कारण से आपके लिए एक वास्तविक मुद्दा है तो कुछ संभावित वर्कअराउंड हैं ...

  1. आप SEQUENCEएक पहचान कॉलम के बजाय उपयोग कर सकते हैं और उदाहरण के लिए एक छोटे कैश आकार को परिभाषित कर सकते हैं और NEXT VALUE FORकॉलम डिफ़ॉल्ट में उपयोग कर सकते हैं।
  2. या ट्रेस ध्वज 272 लागू करें जो IDENTITY2008 R2 तक के संस्करणों के रूप में आवंटन को लॉग इन करता है। यह सभी डेटाबेस पर वैश्विक रूप से लागू होता है।
  3. या, हाल के संस्करणों के लिए, ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE = OFFकिसी विशिष्ट डेटाबेस के लिए पहचान कैशिंग को अक्षम करने के लिए निष्पादित करें।

आपको पता होना चाहिए कि इनमें से कोई भी वर्कअराउंड कोई अंतराल नहीं होने का आश्वासन देता है। इसकी गारंटी कभी नहीं दी गई है IDENTITYक्योंकि यह केवल तालिका में आवेषण को अनुक्रमित करके संभव होगा। यदि आपको एक गैपलेस कॉलम की आवश्यकता है, तो आपको IDENTITYया तो अलग समाधान का उपयोग करने की आवश्यकता होगीSEQUENCE


1
यह सत्यापित करने के लिए कि आपने क्या कहा था कि मैंने कुछ मान डाले हैं और मुझे 1208309, 1208310 मिला है और फिर मैंने सर्वर को फिर से शुरू किया और फिर जब मैंने पंक्ति जोड़ी तो मुझे 1209309 मिला जिसका अर्थ है कि आपने जो कहा है वह बिल्कुल सही है। बहुत बहुत धन्यवाद। अब आप मुझे बता सकते हैं कि मैं इस समस्या को कैसे हल कर सकता हूं। क्या आप मुझे 2012 के बजाय sql सर्वर 2008 का उपयोग करने का सुझाव देंगे जो मैं पहले उपयोग कर रहा था या 2012 का उपयोग करके भी इस समस्या को हल किया जा सकता है ??
काशिफ

1
@ आकाश - क्या यह वास्तव में आपके लिए समस्या है? यहां तक ​​कि अगर आप एक दिन में 1,000 पहचान मूल्यों का उपयोग करते हैं, तो इससे पहले कि आप मानों को चलाने में 2 मिलियन दिनों का समय लेंगे। यदि आप पुराने व्यवहार को चाहते हैं तो आप SQL सर्वर को ट्रेस फ्लैग 272 के साथ स्टार्टअप पर सेट कर सकते हैं या आप SEQUENCEइसके बजाय का उपयोग कर सकते हैं IDENTITYऔर अनुक्रम को कैश आकार में सेट कर सकते हैं 0
मार्टिन स्मिथ

मेरे समाधान धन्यवाद के लिए मुझे आप से काफी प्रभावशाली और संतोषजनक उत्तर मिले।
काशिफ

वास्तव में आपके द्वारा देखा जा CREATE TABLEरहा है कि आप उपयोग कर रहे हैं numeric(7)और उस समय से नंबरिंग शुरू कर दी है 1200001जिसका मतलब है कि आप 8,799दिन (24 वर्ष) के बाद बाहर निकलेंगे यदि आप प्रति दिन 1,000 का उपयोग करते हैं।
मार्टिन स्मिथ

वास्तविक मूल्य "कूद" का उपयोग किए गए स्तंभ प्रकार पर निर्भर माना जाता है। उदाहरण के लिए, एक big intकॉलम आमतौर पर 10,000 प्रति पुनरारंभ द्वारा "कूद" होगा।
स्टारप्लॉट

60

SQL सर्वर को पुनरारंभ करने के बाद यह समस्याएँ होती हैं।

समाधान है:

  • SQL सर्वर कॉन्फ़िगरेशन प्रबंधक चलाएँ ।

  • SQL सर्वर सेवाएँ चुनें ।

    SQL सर्वर कॉन्फ़िगरेशन प्रबंधक

  • SQL सर्वर पर राइट-क्लिक करें और गुण चुनें ।

  • स्टार्टअप पैरामीटर्स के तहत खुलने वाली विंडो में , टाइप -T272करें और Add पर क्लिक करें , फिर Apply बटन दबाएं और पुनरारंभ करें।

    SQL सर्वर स्टार्टअप पैरामीटर


1
यह विधि वास्तव में काम है, बहुत बहुत धन्यवाद! और जैसा कि यहां बताया गया है , यह समस्या SQL सर्वर 2012 में तय नहीं होगी, और यह सर्विस पैक में है, - केवल अगले संस्करण में जारी किया जाएगा।
टुकड़ा

2
क्या व्यक्तिगत डेटाबेस में ट्रेस ध्वज को लागू करने का कोई तरीका है? मैं पूरे सर्वर पर यह परिवर्तन नहीं करना चाहता क्योंकि मेरे पास तृतीय-पक्ष डेटाबेस है और मुझे यकीन नहीं है कि यह उन पर कैसे प्रभाव डालेगा।
इगे एर्सोज़

1
मैंने कारणों का पालन नहीं किया, लेकिन जाहिर तौर पर कुछ उपयोगकर्ताओं को इसे काम करने के लिए निचले मामले "टी" का उपयोग करना पड़ा। ऊपर टिप्पणी में Fragment द्वारा पोस्ट लिंक देखें।
सावेज

33

SQL Server 2017+आप से बदल सकते हैं उपयोग किए जाने वाले परिवर्तन की आवश्यकता :

IDENTITY_CACHE = {ON | रवाना}

डेटाबेस स्तर पर पहचान कैश को सक्षम या अक्षम करता है। डिफ़ॉल्ट पर है। आइडेंटिटी कॉलम के साथ टेबल पर INSERT प्रदर्शन को बेहतर बनाने के लिए आइडेंटिटी कैशिंग का उपयोग किया जाता है। उन मामलों में पहचान कॉलम के मूल्यों में अंतराल से बचने के लिए जहां सर्वर अप्रत्याशित रूप से पुनरारंभ होता है या द्वितीयक सर्वर पर विफल रहता है, IDENTITY_CACHE विकल्प को अक्षम करें। यह विकल्प मौजूदा SQL सर्वर ट्रेस फ्लैग 272 के समान है, सिवाय इसके कि इसे सर्वर स्तर पर बजाय डेटाबेस स्तर पर सेट किया जा सकता है।

(...)

जी। IDENTITY_CACHE सेट करें

यह उदाहरण पहचान कैश अक्षम करता है।

ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE=OFF ;

25

मुझे पता है कि मेरा जवाब पार्टी को देर हो सकता है। लेकिन मैंने SQL Server 2012 में स्टार्ट अप स्टोर की गई प्रक्रिया को जोड़कर एक और तरीके से हल किया है।

मास्टर डीबी में निम्नलिखित संग्रहित प्रक्रिया बनाएं।

USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[ResetTableNameIdentityAfterRestart]
AS
BEGIN

begin TRAN
    declare @id int = 0
    SELECT @id =  MAX(id) FROM [DatabaseName].dbo.[TableName]
    --print @id
    DBCC CHECKIDENT ('[DatabaseName].dbo.[TableName]', reseed, @id)
Commit

END

फिर इसे सिंटैक्स का उपयोग करके स्टार्ट अप में जोड़ें।

EXEC sp_procoption 'ResetOrderIdentityAfterRestart', 'startup', 'on';

यदि आपके पास कुछ टेबल हैं तो यह एक अच्छा विचार है। लेकिन अगर आपको कई तालिकाओं के लिए करना है, तो यह विधि अभी भी काम करती है लेकिन एक अच्छा विचार नहीं है।


अच्छा विचार है। लेकिन यह निर्भर तालिकाओं के लिए काम नहीं करता है, यह करता है? मेरा मतलब है, क्या यह विदेशी प्रमुख मूल्यों को ठीक करता है?
rom5jp

@ rom5jp फिक्सिंग FK इस उत्तर का बिंदु नहीं है। यह एक मेज के संभावित अगले पीके मूल्य को ठीक करने के बारे में है। जब तक MAX (id) किसी भी FK में नहीं है, तब तक काम करना चाहिए।
ज्यारा

14

आकार की परवाह किए बिना कई डेवलपर्स और अनुप्रयोगों के बीच यह अभी भी एक बहुत ही सामान्य मुद्दा है।

दुर्भाग्य से ऊपर दिए गए सुझाव सभी परिदृश्यों को ठीक नहीं करते हैं, अर्थात साझा होस्टिंग, आप -272 स्टार्टअप पैरामीटर सेट करने के लिए अपने होस्ट पर भरोसा नहीं कर सकते।

इसके अलावा, यदि आपके पास मौजूदा टेबल्स हैं जो प्राथमिक कुंजियों के लिए इन पहचान स्तंभों का उपयोग करते हैं, तो यह उन स्तंभों को छोड़ने और बीएस अनुक्रम वर्कअराउंड का उपयोग करने के लिए नए लोगों को फिर से बनाने का एक बड़ा प्रयास है। अनुक्रम वर्कअराउंड केवल तभी अच्छा होता है जब आप SQL 2012+ में स्क्रैच से नए टेबल को डिज़ाइन कर रहे हों

लब्बोलुआब यह है, अगर आप Sql Server 2008R2 पर हैं, तो STAY ON IT। गंभीरता से, इस पर बने रहें। जब तक Microsoft यह स्वीकार नहीं करता है कि उन्होंने एक बड़ा बग पेश किया है, जो अभी भी Sql Server 2016 में है, तब तक हमें इसे अपग्रेड नहीं करना चाहिए और जब तक वे इसे FIX नहीं करते।

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

मैं अपने द्वारा उपयोग किए जाने वाले वर्कअराउंड को साझा करूंगा, क्योंकि My DB की साझा होस्टिंग सर्वर पर हैं, साथ ही, मैं अपने प्राथमिक कुंजी कॉलम को ड्राप और रीक्रिएट नहीं कर रहा हूं, जो कि एक विशाल पीटीए होगा।

इसके बजाय, यह मेरी शर्मनाक हैक है (लेकिन इस पीओएस बग के रूप में शर्मनाक नहीं है जो कि माइक्रोसॉफ्ट ने पेश किया है)।

हैक / फिक्स:

अपने सम्मिलित आदेशों से पहले, बस प्रत्येक प्रविष्टि से पहले अपनी पहचान फिर से बनाएं। यदि आप अपने Sql सर्वर इंस्टेंस पर व्यवस्थापक नियंत्रण नहीं रखते हैं, तो यह फिक्स केवल अनुशंसित है, अन्यथा मेरा सुझाव है कि सर्वर को पुनः आरंभ करने पर।

declare @newId int -- where int is the datatype of your PKey or Id column
select @newId = max(YourBuggedIdColumn) from YOUR_TABLE_NAME
DBCC CheckIdent('YOUR_TABLE_NAME', RESEED, @newId)

आपके डालने से ठीक पहले वे 3 पंक्तियाँ, और आपको जाने के लिए अच्छा होना चाहिए। यह वास्तव में प्रदर्शन को इतना प्रभावित नहीं करेगा, अर्थात यह ध्यान देने योग्य नहीं होगा।

सौभाग्य।


7

पहचान मूल्यों को कूदने के कई संभावित कारण हैं। वे प्रतिकृति के लिए पहचान प्रबंधन के लिए लुढ़का पीछे आवेषण से लेकर। आपके मामले में यह क्या कारण है जो मैं आपके सिस्टम में कुछ समय बिताए बिना नहीं बता सकता।

हालाँकि, आपको पता होना चाहिए कि किसी भी स्थिति में आप एक पहचान कॉलम को कॉनगिग नहीं मान सकते हैं। बस बहुत सी चीजें हैं जो अंतराल का कारण बन सकती हैं।

आप इसके बारे में थोड़ी और जानकारी यहाँ पा सकते हैं: http://sqlity.net/en/792/the-gap-in-the-identity-value-fterence/

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