MySQL ऑटो-इन्क्रीमेंट फ़ील्ड अपने आप रीसेट करता है


12

हमारे पास एक MySQL टेबल है जिसमें एक ऑटो-इन्क्रिमेंटिंग फ़ील्ड एक INT (11) के रूप में सेट है। यह तालिका बहुत अधिक नौकरियों की सूची संग्रहीत करती है जो किसी एप्लिकेशन में चल रही हैं। आवेदन के जीवनकाल के दौरान किसी भी समय, तालिका में हजारों प्रविष्टियां हो सकती हैं या पूरी तरह से खाली हो सकती हैं (यानी सब कुछ समाप्त हो गया है)।

यह क्षेत्र किसी और चीज़ के लिए विदेशी नहीं है।

ऑटो-इंक्रीमेंट बेतरतीब ढंग से खुद को शून्य पर रीसेट करने के लिए लगता है, हालांकि हम वास्तव में रीसेट को फंसाने में कभी सक्षम नहीं हुए हैं।

समस्या स्पष्ट हो जाती है क्योंकि हम देखते हैं कि ऑटो-इन्क्रीमेंट फ़ील्ड 600,000 रिकॉर्ड या तो उठ जाती है, और फिर कुछ समय बाद ऑटो-इन्क्रिमेंट फ़ील्ड कम 1000 में चलती है।

यह लगभग वैसा ही है जैसे यदि टेबल खाली है तो ऑटो-इन्क्रीमेंट स्वयं रीसेट करता है।

क्या यह संभव है और अगर यह है, तो मैं इसे कैसे बंद करूं या इसके तरीके को बदलूं?

यदि ऐसा नहीं है, तो क्या किसी के पास इसका स्पष्टीकरण है कि यह ऐसा क्यों हो सकता है?

धन्यवाद!


MySQL का क्या संस्करण? लेनदेन या प्रतिकृति उपयोग में हैं?
18

जवाबों:


26

ऑटो-इंक्रीमेंट काउंटर केवल मुख्य मेमोरी में संग्रहीत किया जाता है, डिस्क पर नहीं।

http://dev.mysql.com/doc/refman/4.1/en/innodb-auto-increment-handling.html

इसके कारण जब सेवा (या सर्वर) पुनः आरंभ होता है तो निम्न होगा:

सर्वर स्टार्टअप के बाद, तालिका में पहली बार सम्मिलित करने के लिए, InnoDB इस कथन के समतुल्य निष्पादित करता है: अद्यतन MAX (ai_col) FROM t for UPDATE;

InnoDB एक विवरण द्वारा प्राप्त मूल्य से वृद्धि करता है और इसे स्तंभ और तालिका के लिए ऑटो-वृद्धि काउंटर पर असाइन करता है। यदि तालिका खाली है, तो InnoDB मान 1 का उपयोग करता है।

सादे अंग्रेजी में, MySQL सेवा शुरू होने के बाद यह पता नहीं है कि आपकी मेज के लिए ऑटो-इंक्रीमेंट मूल्य क्या होना चाहिए। इसलिए जब आप पहली बार एक पंक्ति सम्मिलित करते हैं, तो यह उस क्षेत्र का अधिकतम मूल्य पाता है जो ऑटो-इंक्रीमेंट का उपयोग करता है, इस मूल्य में 1 जोड़ता है, और परिणामी मूल्य का उपयोग करता है। यदि कोई पंक्तियाँ नहीं हैं, तो यह 1 पर शुरू होगी।

यह हमारे लिए एक समस्या थी, क्योंकि हम टेबल और mysql के ऑटो-इन्क्रीमेंट फ़ीचर का उपयोग बहु-थ्रेडेड वातावरण में IDs को बड़े करीने से प्रबंधित करने के लिए कर रहे थे जहाँ उपयोगकर्ताओं को तृतीय-पक्ष भुगतान साइट पर पुनः निर्देशित किया जा रहा था। इसलिए हमें यह सुनिश्चित करना था कि आईडी थर्ड पार्टी को मिले और हमें वापस भेजे जाने का तरीका अनूठा था और इस तरह से रहेगा (और निश्चित रूप से उपयोगकर्ता द्वारा लेनदेन को रद्द किए जाने के बाद उपयोगकर्ता को रद्द करना होगा)।

इसलिए हम एक पंक्ति बना रहे थे, उत्पन्न ऑटो-इन्क्रिमेंट मान प्राप्त कर रहे थे, तालिका को साफ रखने के लिए पंक्ति को हटा रहे थे, और मूल्य को भुगतान साइट पर अग्रेषित कर रहे थे। जिस तरह से एएनओडीबी हैंडल करता है उसे एआई मानों के मुद्दे को ठीक करने के लिए हमने समाप्त किया था जो निम्नलिखित था:

$query = "INSERT INTO transactions_counter () VALUES ();";
mysql_query($query);
$transactionId = mysql_insert_id();
$previousId = $transactionId - 1;
$query = "DELETE FROM transactions_counter WHERE transactionId='$previousId';";
mysql_query($query); 

यह हमेशा टेबल में एक पंक्ति के रूप में उत्पन्न नवीनतम ट्रांजैक्शन को चालू रखता है, बिना अनावश्यक रूप से तालिका को उड़ाए बिना।

आशा है कि किसी और की मदद करता है जो इसमें भाग सकता है।

संपादित करें (2018-04-18) :

जैसा कि नीचे उल्लेख चालाकी से प्रतीत होता है कि इस का व्यवहार MySQL 8.0+ में संशोधित किया गया है।

https://dev.mysql.com/worklog/task/?id=6204

उस कार्यक्षेत्र में शब्दांकन सबसे अच्छा दोषपूर्ण है, हालांकि यह उन नए संस्करणों में InnoDB दिखाई देता है जो अब रिबूट में लगातार ऑटोइनक मानों का समर्थन करते हैं।

-Gremio


पहली पोस्ट के लिए बुरा नहीं है, दोस्त। +1।
सिजॉयज

ज्ञान की मीठी बिट वहाँ ग्रेमियो। धन्यवाद!! मैंने इसे पूरी तरह से बंद कर दिया था और बाद की तारीख में समीक्षा करने के लिए इस मुद्दे को आंतरिक रूप से संग्रहीत किया था, लेकिन इसके चारों ओर वापस आने से आपका समाधान एक आकर्षण का काम करता है!
होलिगांट

3

हमने इस समस्या का अनुभव किया है और पता लगाया है कि जब एक खाली टेबल पर ऑप्टिमाइज़ टेबल चलती थी, तो ऑटो-इंक्रीमेंट वैल्यू भी रीसेट हो जाती थी। इस MySQL बग रिपोर्ट को देखें ।

वर्कअराउंड के रूप में, आप यह कर सकते हैं:

ALTER TABLE a AUTO_INCREMENT=3 ENGINE=innoDB;

के बजाय OPTIMIZE TABLE

ऐसा लगता है कि यह MySQL आंतरिक रूप से करता है (ऑटो वेतन वृद्धि मूल्य को स्थापित किए बिना, जाहिर है)


2

बस अंधेरे में एक शॉट - अगर आवेदन TRUNCATE TABLEप्रसंस्करण किए जाने पर तालिका को खाली करने के लिए उपयोग कर रहा है, तो यह ऑटो-इन्क्रीमेंट फ़ील्ड को रीसेट करेगा। यहाँ प्रश्न पर एक संक्षिप्त चर्चा है । हालांकि उस लिंक में उल्लेख किया गया है कि InnoDB एक ट्रंक पर auto_increments को रीसेट नहीं करता है, जिसे बग के रूप में रिपोर्ट किया गया था और कुछ साल पहले तय किया गया था।

मेरे अनुमान को सही मानते हुए, आप समस्या को ठीक करने के लिए ट्रंकटिंग से डिलीट करने के लिए बदल सकते हैं।


मुझे नहीं लगा कि हम TRUNCATE का उपयोग कर रहे थे, लेकिन हमें यह सुनिश्चित करने के लिए जांचना था। यहां तक ​​कि यह सुनिश्चित करने के लिए PHP ड्राइवर स्तर तक नीचे सत्यापित करने के लिए चला गया। हम नहीं थे हालांकि संभव समाधान की सराहना करते हैं।
Hooligancat

1

केवल उस मूल्य का एक स्पष्ट रीसेट, या उस क्षेत्र का एक ड्रॉप / रिक्रिएट, या अन्य समान हिंसक ऑपरेशन को कभी भी एक auto_increment काउंटर रीसेट करना चाहिए। (TRUNCATE वास्तव में एक अच्छा सिद्धांत था।) यह असंभव लगता है कि आप अचानक 32-बिट INT को लपेट रहे हों जब अंतिम साक्षी केवल 600k हो। यह निश्चित रूप से बस रीसेट नहीं करना चाहिए क्योंकि तालिका खाली हो जाती है। आपके पास mysql बग या आपके PHP कोड में कुछ है। या अगले दरवाजे में क्यूबिकल में लड़का आप पर एक चाल खेल रहा है।

आप बाइनरी लॉग ऑन करके डीबग कर सकते हैं , क्योंकि इसमें इस तरह के स्टेटमेंट होंगे:

SET INSERT_ID=3747670/*!*/;

फिर कम से कम आप काउंटर टेबल से ठीक पहले सहित उस तालिका के हर विवरण को देख सकते हैं।


डिबग टिप के लिए धन्यवाद। जब से मुझे सर्वरफोल में जांच करने की जरूरत पड़ी, मुझे आपकी टिप की सराहना करते हुए कुछ समय हो गया है
Hooligancat

0

सारणी तालिका_नाम इंजन = MyISAM

मेरे लिए काम करता है। हमारी तालिका को हमेशा बहुत छोटा रखा जाता है, इसलिए InnoDB की कोई आवश्यकता नहीं है।


क्या आपको लेनदेन की आवश्यकता है?
एंथनी रटलेज

0

InnoDB डिस्क पर ऑटो इंक्रीमेंट वैल्यू को स्टोर नहीं करता है, इसलिए जब MySQL सर्वर बंद हो जाता है तो वह इसे भूल जाता है। जब MySQL फिर से शुरू किया जाता है, तो InnoDB इंजन ऑटो वेतन वृद्धि मूल्य को इस तरह से पुनर्स्थापित करता है SELECT (MAX(id) + 1) AS auto_increment FROM table:। यह एक बग है जो MySQL संस्करण 8.0 में तय किया गया है।

समस्या को हल करने के लिए टेबल इंजन बदलें:

ALTER TABLE table ENGINE = MyISAM

या रिलीज़ होने पर MySQL सर्वर को संस्करण 8.0 में अपडेट करें।

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