サーバーの再起動後にInnodbデータベースのauto_increment IDがリセットされないようにします


11

私は最近、サーバーの再起動時にInnoDBがAUTO_INCREMENT値を再計算する方法のため、IDリストの上限にあるすべてのレコードのIDが再利用される可能性があることを最近読みました。

ユーザーが削除されると、IDに関連付けられたすべてのものが他のテーブルからも削除されるため、通常、これは問題にはなりません。

ただし、過去の会話が維持されるように、「= User#123 =による投稿」というラベルが付けられたフォーラム投稿を意図的に孤立させておきます。明らかに、IDが再利用される場合、これは問題になります。

この方法でIDが再利用される可能性を低くするのに十分な数の新しいユーザーが常にいるため、私はこれまでこの問題に遭遇したことがありません。ただし、私の新しいプロジェクトでは、サインアップはまれであり、非アクティブなユーザーの削除が頻繁に行われ(特に、「Open Alpha」アカウントはプレビューとして3日間しか持続しないため)、そのようなIDの再利用は3〜3回発生しています。

AUTO_INCREMENTの正しい値を他の場所に保存し、内部値に依存する代わりにそれを使用することにより、問題を「修正」しました。InnoDBに実際の最後の値を記憶させる実際の方法はありますか?


あなたが読んだ記事はありますか?
gbn 2012



ALTER TABLE table_name ENGINE = MyISAMは私のために働きます。テーブルは常に非常に小さく保たれているため、InnoDBは必要ありません。

1
@QuickFix これが機能する理由についての詳細を追加する必要があります。
マックスヴァーノン

回答:


5

(削除しないことで問題を回避)

"Posted by =User #123="ユーザーを削除した後も情報を保持したいのでid=123、ユーザーのデータを格納するために2つのテーブルを使用することも検討できます。1つはActiveユーザー用、もう1つはすべて(アクティブユーザーから削除されたものを含む)。また、これらのIDを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

もちろん、これは新しいユーザーの挿入操作を複雑にします。すべての新規ユーザーは、各テーブルに1つずつ、2つの挿入を意味します。ただし、ユーザーを削除するには、ActiveUserテーブルからのみ削除します。Alluserテーブルを参照するフォーラムの投稿を除いて、すべてのFKはカスケードで削除されます(削除は行われません)。


4

これを行う自然な方法はありません。ただし、information_schema.tablesを使用して、auto_incrementオプションですべての列を記録します。

これらの列は次のように収集できます。

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}

次に、次の2つのいずれかを行います。

オプション#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ドキュメントは、あなたが既に持っているとして、他の場所で自動インクリメント値を格納することを示唆しています。

別の解決策は、実際のテーブル自体で自動インクリメントを使用しないようにSEQUENCEをエミュレートすることです。これは、SO何度議論されています。MySQLのパフォーマンスのブログはそれを言及しています。

他のRDBMSにはない、もう1つのMySQLデータねじ込み...


2

ユーザーを削除しないでください。関係の整合性はより重要です。プライバシー上の理由などが必要な場合は、ユーザー名を「削除済み」に変更し、他のフィールドをすべてクリアしてください。


1

これは古い質問であり、依然として関連しています。

1)この動作はMysql 8.0で修正されています。

2)1つの解決策は、データにダミー行を使用して、AUTO_INCREMENTを特定の値より上に保つことです。保存する内容によってはそれほど便利ではありませんが、場合によっては簡単な解決策です。


0

この必要性があったため、この投稿の指示に基づいて、独自のシステムのソリューションを推定しました。これにより、誰でも簡単に目標を達成できる場合。

切断されたシステムで双方向の同期を行うため、システムはトゥームストーンテーブルパターンを使用して削除済みアイテムを保存します。このコードを使用してトゥームストーンテーブルをライブテーブルと照合し、可能な限り高い値を抽出します:)

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 ;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.