14

自動インクリメントの主キーを持つテーブルがあります。このテーブルは何百万ものレコードを格納するためのものであり、今のところ何も削除する必要はありません。問題は、新しい行が挿入されるときに、何らかのエラーが原因で、自動インクリメント キーが自動インクリメント ID にギャップを残すことです。たとえば、5 の後、次の ID は 8 で、6 と 7 のギャップが残ります. この結果、行数をカウントすると 28000 になりますが、最大 ID は 58000 です。理由は何ですか? 私は何も削除していません。そして、どうすればこの問題を解決できますか。

PSレコードを挿入するときに挿入無視を使用しているため、重複するエントリを一意の列に挿入しようとするとエラーが発生しません。

4

5 に答える 5

20

これは仕様によるものであり、常に発生します。

なんで?

INSERT を実行している 2 つの重複するトランザクションを見てみましょう

  • トランザクション 1 は INSERT を実行し、値 (42 としましょう) を取得し、さらに作業を行います
  • トランザクション 2 は INSERT を実行し、値 43 を取得し、さらに作業を行います

それで

  • トランザクション 1 は失敗します。ロールバックします。42 未使用のまま
  • トランザクション 2 は 43 で完了します

連続した値が保証されている場合、すべてのトランザクションは次々に発生する必要があります。あまりスケーラブルではありません。

また、挿入されたレコードは常に連続した ID 値を受け取るかを参照してください(SQL Server ですが、同じ原則が適用されます) 。

于 2013-05-16T08:40:44.000 に答える
2

次のように自動インクリメントを処理するトリガーを作成できます。

CREATE DEFINER=`root`@`localhost` TRIGGER `mytable_before_insert` BEFORE INSERT ON `mytable` FOR EACH ROW 
BEGIN
  SET NEW.id = (SELECT IFNULL(MAX(id), 0) + 1 FROM mytable);;
END
于 2016-01-22T13:53:19.243 に答える
2

これは、MySQL のストレージ エンジンである InnoDB の問題です。

「<a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html" rel= のドキュメントを確認するときのように、実際には問題ありません。 「nofollow noreferrer">AUTO_INCREMENT InnoDB での処理」は基本的に、InnoDB が起動時に自動インクリメントを行うために特別なテーブルを使用することを示しています。

そして、それが使用するクエリは次のようなものです

SELECT MAX(ai_col) FROM t FOR UPDATE;

これにより、データに実際に影響を与えることなく同時実行性が向上します。

ストレージ エンジンとして InnoDB の代わりに MyISAM を使用しないようにするには

于 2013-05-16T08:47:20.787 に答える