MySQL-最後の行が削除された場合、自動インクリメントは連続してインクリメントしません


8

自動インクリメントされた主キーIDを含むテーブルがあります。最後の行(たとえば、最高のID、たとえばid = 6)を削除して新しい行を挿入すると、新しいIDは7から始まります。主キーが6から始まることを変更する必要があるパラメーターはどれですか。

CREATE TABLE animals (
 id MEDIUMINT NOT NULL AUTO_INCREMENT,
 name CHAR(30) NOT NULL,
 PRIMARY KEY (id)
) ENGINE=MyISAM;

INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');

結果:
ID名
1犬
2猫
3ペンギン
4亜麻
5クジラ
6ダチョウ

DELETE FROM animals WHERE id = 6;
INSERT INTO animals (name) VALUES
('x');

結果:
ID名
1犬
2猫
3ペンギン
4緩い
5クジラ
7 x

アドバイスをありがとう。


では、ギャップがあるとどうなりますか?(いくつかの他の理由だけでなく、行を削除することによって起因現れることができる)
ypercubeᵀᴹ

挿入後に削除が発生した場合はどうしますか?それらのギャップを再利用しますか?はい、その場合、Identityはその列に適切なタイプではないと思います。これにより、その列の一意の値を気にする必要がなくなります。値を順番に保持する場合は、通常のINT / BIGINTタイプのデータタイプを使用できます。欠落しているすべてのギャップの値を検索/再利用/リセットすることは、アイデンティティプロパティの目的を没収するようなものです。
Anup Shah 2013

@giordano AUTO_INCREMENT PRIMARY KEYの端正なフリークになりたいのはなぜですか。あなたは/更新によるフラグメンテーションに削除...場合は、「ギャップ」があなたのテーブルのデータでもあり、それに対処する
レイモンドNijland

私はしばらく前にSQL Serverの継続的なauto_increment値について調査しました:sqlity.net/en/792/the-gap-in-the-identity-value-sequence-それはMySQL向けではありませんが、基礎となるメカニズムは同じですなので、同様の結果が得られます。つまり、自動生成されたシーケンスのギャップを防ぐことはできません。
Sebastian Meine 2013年

@ypercube:回答ありがとうございます。確かに、私は別のより複雑な例から得たギャップですが、最小限の例を示したかったのです。実際の例は、(1)属性の変更による行の有効期限の変更(例:製品テーブルから)、および(2)同じ製品コード、新しい属性、新しい発効日、および有効期限のある新しい製品の追加です。日付。起こったことは、新しい主キーが+1ではなく+2で自動インクリメントされなかったことです。明らかに、ステップ(1)または(2)には、目に見えない自動インクリメントがあります。ギャップの他の理由は何でしょうか。
giordano 2013年

回答:


12

これは設計によるものです。すべてのDBMSは、これを自動インクリメント列で実行していました。

それらを行わなかった場合、外部参照整合性が損傷する可能性があります。この簡単な例として、自動インクリメント列をキーとして使用して、短縮サービスのURLを保存しているとします。短縮URLがまだ誰にも配布されていないかどうかはわかりませんし、データベースも確かに配布されていないため、ID 1234を再利用すると、http:/ /shortthi.ng/1234は、「申し訳ありませんが、このリンクはレコードに存在しません」というメッセージを代わりに、古いメールにれています。

また、最後のアイテムを削除した後に増分をリセットすると、5番目のアイテムが削除されたときに、500万の5番目のアイテム以降のすべての番号を付け直すすべての作業(またはデータベースが期待すること)も実行されますか?インクリメント列を指す外部キー制約である他のテーブルへの変更を完了しましたか?そのような余分な作業は、IOに関しては非常に高価になる可能性があります。

あなたするなら最後の項目を削除した後インクリメントポイントをリセットし、あなたのトランザクション分離レベルの非常に非常に気をつけてください:あなたは別のトランザクションがエラー(または悪化し、サイレント障害)につながる、値を使用すると同じように、それをリセットするかもしれない、しない限り、アクションが完全に分離されていることを確認します。

私は通常、データベースで作業している人に、この問題に関する「疑似キーニートフリークス」という章がある「SQLアンチパターン」を読むことをお勧めします(章のタイトルが示唆しているよりもわかりやすい方法で問題をカバーしています!)。基本的に、値がキー(またはせいぜい挿入順序情報)を超える意味を持つ場合、おそらく自動インクリメント列であってはならず、キー(またはせいぜい挿入順序情報)以外の意味がない場合情報)ギャップは重要ではありません。


この説明をありがとう。鍵となる概念をより深く理解する必要があると思います。自動インクリメントメカニズムがどのように機能するのか疑問に思います。削除しなかったが、1つの行を変更(更新)して新しい行を追加したときに、主キーにもギャップがあったためです。間違いなく、自動インクリメント値を手動で変更することはしません。
giordano 2013年

「重要な概念の詳細」については、Bill KarwinによるSQL Antipatternsブックを強くお勧めします。これは、このトピックと他の一般的な(それほど一般的ではない)トピックをカバーし、間違った方法、なぜ一般的な間違っているのかについて説明メソッドは問題を引き起こし、それらをどのように修正するか、そして「間違った」メソッドが簡潔でアクセス可能な方法でとにかく(または唯一の選択肢)使用してもよい場合があります。
David Spillett 2013年

Spillet:この指摘に感謝します。今読んだのでとても助かりました。InnoDBテーブルとMyISAMテーブルを異なるカウントなぜそれにもかかわらず、私は理解していない:dba.stackexchange.com/questions/51883/...
ジョルダーノ

0

以下を使用してauto_increment値をリセットできます。

ALTER TABLE MyTable AUTO_INCREMENT = 1234;

上記のステートメントで使用するには、テーブルに存在する最大値を決定し、その値に1を追加する必要があります。


これが悪いと、「ほとんどすべての」MySQLバージョンでテーブルを読み書きできなくなります。MySQL 5.6はLIVE ALTERを実行できますが、テーブルをロックする必要がある場合もあります。
Raymond Nijland 2013年

2
@RaymondNijland誰もが気付くほどロックが長く続くとは思いません。
ypercubeᵀᴹ

@マックス、レイモンド、ypercube:答えてくれてありがとう。このような変更は避けます。
giordano 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.