सर्वर पुनः आरंभ करने के बाद इनोडब डेटाबेस में स्वतः_संचालन आईडी के रीसेट को रोकें


11

मैंने हाल ही में पढ़ा कि सर्वर के पुनः आरंभ होने पर InnoDB AUTO_INCREMENT मान को कैसे पुन: प्राप्त करता है, इस कारण आईडी सूची के उच्च अंत पर किसी भी रिकॉर्ड का आईडी का पुन: उपयोग हो सकता है।

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

लेकिन मैं जानबूझकर उनके मंच के पदों को अनाथ छोड़ रहा हूं, जिन्हें "Posted by = User # 123 =" के रूप में लेबल किया गया है, ताकि पिछली बातचीत बरकरार रहे। स्पष्ट रूप से, क्या एक आईडी का पुन: उपयोग किया जाना चाहिए, यह एक समस्या होगी।

मेरे पास यह मुद्दा पहले कभी नहीं था क्योंकि आईडी के लिए इस तरह से पुन: उपयोग किए जाने की संभावना नहीं थी, इसलिए हमेशा पर्याप्त नए उपयोगकर्ता थे। हालाँकि मेरे नए प्रोजेक्ट पर साइन अप दुर्लभ और निष्क्रिय उपयोगकर्ता विलोपन हैं (विशेषकर जब से "ओपन अल्फा" खाते केवल पूर्वावलोकन के रूप में तीन दिनों तक चलते हैं), और ऐसे आईडी पुन: उपयोग अब तीन के लिए तीन हो गए हैं।

मैंने AUTO_INCREMENT के लिए सही मूल्य बचाकर और आंतरिक मूल्य पर निर्भर रहने के बजाय इसका उपयोग करके "समस्या" को निर्धारित किया है। वहाँ एक वास्तविक तरीका है InnoDB वास्तविक अंतिम मूल्य याद है?


क्या आपके पास लेख पढ़ा है?
gbn

@gbn लेख के लिए लिंक dev.mysql.com/doc/refman/5.1/en/…
नवीन कुमार

इस संदर्भ के लिए यह बगैस्मिस्सकल.com
लौरिनस बेविनीस

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

1
@QuickFix आपको इस बारे में कुछ विवरण जोड़ना चाहिए कि यह क्यों काम करता है।
मैक्स वेरनॉन

जवाबों:


5

(कभी नहीं हटाकर मुद्दे से बचना)

चूंकि आप "Posted by =User #123="उपयोगकर्ता को हटाने के बाद जानकारी रखना चाहते हैं, इसलिए आप id=123उपयोगकर्ताओं के डेटा को संग्रहीत करने के लिए 2 तालिकाओं का उपयोग करने पर भी विचार कर सकते हैं। Activeउपयोगकर्ताओं के लिए एक और सभी के लिए एक (सक्रिय उपयोगकर्ताओं से हटाए गए सहित)। और उन आईडी को AllUserतालिका से कभी न हटाएं :

CREATE TABLE AllUser
( user_id INT AUTO_INCREMENT
, ...
, PRIMARY KEY (user_id)
) ;

------
--- Forum posts FK should reference the `AllUser` table

CREATE TABLE ActiveUser
( user_id INT 
, ...
, PRIMARY KEY (user_id)
, FOREIGN KEY (user_id)
    REFERENCES AllUser (user_id)
) ;

------
--- All other FKs should reference the `ActiveUser` table

यह निश्चित रूप से सम्मिलित नए उपयोगकर्ता ऑपरेशन को जटिल करेगा। किसी भी नए उपयोगकर्ता का अर्थ 2 आवेषण होगा, प्रत्येक तालिका में एक। एक उपयोगकर्ता को हटाना हालांकि ActiveUserकेवल तालिका से हटाकर होगा । फ़ोरम पोस्ट को छोड़कर सभी FK को कैस्केडिंग के साथ हटा दिया जाएगा, जो कि Alluserतालिका को संदर्भित करेगा (जहाँ कोई डिलीट कभी नहीं होगा)।


4

Auto_increment विकल्प वाले सभी कॉलम को रिकॉर्ड करने के लिए information_schema.tables का उपयोग करने के अलावा ऐसा करने का कोई प्राकृतिक तरीका नहीं है।

आप उन स्तंभों को इस प्रकार एकत्रित कर सकते हैं:

CREATE TABLE mysql.my_autoinc ENGINE=MyISAM
SELECT table_schema,table_name,auto_increment
FROM information_schema.tables WHERE 1=2;
ALTER TABLE mysql.my_autoinc ADD PRIMARY KEY (table_schema,table_name);
INSERT INTO mysql.my_autoinc
SELECT table_schema,table_name,auto_increment
FROM information_schema.tables WHERE auto_increment IS NOT NULL;

एक स्क्रिप्ट बनाएं जो auto_increment मान रीसेट करेगा

AUTOINC_SCRIPT=/var/lib/mysql/ResetAutoInc.sql
mysql -u... -p... -AN -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' AUTO_INCREMENT=',auto_increment,';') FROM mysql.my_autoinc" > ${AUTOINC_SCRIPT}

फिर आप दो काम कर सकते हैं:

विकल्प # 1: स्टार्टअप के बाद मैन्युअल रूप से स्क्रिप्ट चलाएँ

mysql> source /var/lib/mysql/ResetAutoInc.sql

विकल्प # 2: कनेक्शन की अनुमति देने से पहले mysqld स्क्रिप्ट निष्पादित करें

आपको यह विकल्प जोड़ना होगा

[mysqld]
init-file=/var/lib/mysql/ResetAutoInc.sql

इस तरह, हर बार जब आप mysql को पुनरारंभ करते हैं, तो इस स्क्रिप्ट को शुरुआत में निष्पादित किया जाता है। एक योजनाबद्ध mysql पुनरारंभ करने से पहले आपको /var/lib/mysql/ResetAutoInc.sql को पुनः प्राप्त करना याद रखना होगा।


3

5.5 डॉक्स ऑटो वृद्धि मान कहीं और भंडारण का सुझाव आपके पास पहले से है।

एक वैकल्पिक समाधान एक दृश्य का अनुकरण करना होगा ताकि आप वास्तविक तालिका में स्वतः-वृद्धि का उपयोग न करें। इस पर पहले और फिर एसओ से चर्चा हुई हैMySQL प्रदर्शन ब्लॉग यह उल्लेख है।

अभी तक एक अन्य MySQL डेटा है कि अन्य RDBMS नहीं है ...


2

बस उपयोगकर्ता को हटाएं नहीं। संबंधपरक अखंडता अधिक महत्वपूर्ण है। यदि आपके पास गोपनीयता कारणों या जो कुछ भी है, तो बस उपयोगकर्ता नाम को 'हटाए' में बदलें और किसी अन्य फ़ील्ड को साफ़ करें।


1

यह एक पुराना सवाल है और अभी भी प्रासंगिक है।

1) यह व्यवहार मैसकल 8.0 में तय किया जा रहा है।

2) एक समाधान अपने डेटा के लिए एक डमी पंक्ति का उपयोग करना है, एक निश्चित मूल्य से ऊपर AUTO_INCREMENT रखना। जो आप स्टोर कर रहे हैं, उसके आधार पर सुपर सुविधाजनक नहीं है, लेकिन कुछ मामलों में एक सरल समाधान है।


0

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

हमारा सिस्टम हटाए गए आइटम को संग्रहीत करने के लिए एक tombstone टेबल पैटर्न का उपयोग करता है क्योंकि हम डिस्कनेक्ट किए गए सिस्टम पर 2 तरह से सिंक करते हैं, इसलिए हम इस कोड का उपयोग अपने लाइव टेबल के साथ tombstone टेबल से मिलान करने और उच्चतम मान को निकालने के लिए करते हैं :)

DROP PROCEDURE IF EXISTS `reset_auto_increments`;
DELIMITER $
CREATE PROCEDURE reset_auto_increments()
BEGIN

    DECLARE done INT DEFAULT 0;
    DECLARE schemaName VARCHAR(255) DEFAULT '';
    DECLARE liveTableName VARCHAR(255) DEFAULT '';
    DECLARE tombstoneTableName VARCHAR(255) DEFAULT '';
    DECLARE liveAutoIncrement INT DEFAULT 0;
    DECLARE tombstoneAutoIncrement INT DEFAULT 0;
    DECLARE newAutoIncrement INT DEFAULT 0;

    DECLARE autoIncrementPairs CURSOR FOR 
        SELECT
            liveTables.TABLE_SCHEMA AS schemaName,
            liveTables.TABLE_NAME AS liveTable, 
            tombstoneTables.TABLE_NAME AS tombstoneTable,
            liveTables.AUTO_INCREMENT AS live_auto_increment,
            tombstoneTables.AUTO_INCREMENT AS tombstone_auto_increment,
            GREATEST(liveTables.AUTO_INCREMENT, tombstoneTables.AUTO_INCREMENT) AS new_auto_increment
        FROM 
            information_schema.tables AS liveTables
            JOIN information_schema.tables AS tombstoneTables
                ON liveTables.TABLE_SCHEMA = tombstoneTables.TABLE_SCHEMA
                    AND CONCAT('deleted', UCASE(LEFT(liveTables.TABLE_NAME, 1)), SUBSTRING(liveTables.TABLE_NAME, 2))
                        = tombstoneTables.TABLE_NAME
        WHERE
            GREATEST(liveTables.AUTO_INCREMENT, tombstoneTables.AUTO_INCREMENT) IS NOT NULL;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    SET done = 0;

    SET schemaName = '';
    SET liveTableName = '';
    SET tombstoneTableName = '';
    SET liveAutoIncrement = 0;
    SET tombstoneAutoIncrement = 0;
    SET newAutoIncrement = 0;

    OPEN autoIncrementPairs;
    REPEAT

        FETCH autoIncrementPairs INTO 
            schemaName, 
            liveTableName, 
            tombstoneTableName, 
            liveAutoIncrement, 
            tombstoneAutoIncrement, 
            newAutoIncrement;

        SET @statement = CONCAT('ALTER TABLE ', schemaName, '.', liveTableName, ' AUTO_INCREMENT=', newAutoIncrement);
        PREPARE updateAutoIncrementStatement FROM @statement;
        EXECUTE updateAutoIncrementStatement;
        DEALLOCATE PREPARE updateAutoIncrementStatement;

    UNTIL done END REPEAT;

    CLOSE autoIncrementPairs;

END$

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