web-dev-qa-db-ja.com

なぜ自動インクリメントは、挿入された行数を超えてジャンプするのですか?

ストアドプロシージャを使用して一括挿入を実行した後、BidsテーブルのbidIDに記録されたauto_increment値に見られるこの奇妙な動作に非常に混乱しています。

INSERT INTO Bids (itemID, buyerID, bidPrice)
 SELECT itemID, Rand_id(sellerID, user_last_id), FLOOR((1 + Rand())*askPrice)
 FROM Items
 WHERE closing BETWEEN NOW() AND NOW() + INTERVAL 1 WEEK ORDER BY Rand() LIMIT total_rows;

たとえば、auto_increment bidIDの値が最初は101で、100行挿入した場合、終了値は201ではなく213になります。

以下を確認して、

SHOW VARIABLES LIKE 'auto_inc%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+

なぜそれが起こっているのか私にはわかりません。 auto increment値のジャンプの原因は何ですか?

11

これは珍しいことではなく、いくつかの原因があります。クエリランナーがカウンターリソースとの競合の問題を減らすために最適化したことが原因である場合があり、影響を受けるテーブルへの同時更新がある場合の効率が向上します。明示的にロールバックされた(またはエラーが発生したために暗黙的にロールバックされた)トランザクションが原因である場合があります。

auto_increment列(またはMSSQLのIDENTITY、および概念が通っている他の名前)からの唯一の保証は、各値が一意であり、以前の値よりも小さくなることはないということです。順序付けの値に基づいていますが、ギャップがないとは限りません。

列の値にギャップがないようにする必要がある場合は、ビジネスロジックの別のレイヤーまたはトリガーを介してDBで値を自分で管理する必要があります(ただし、トリガーの潜在的なパフォーマンスの問題に注意してください)。自分でロールする場合は、DBエンジンがギャップを許可することで回避する、すべての同時実行性/ロールバック/削除後のクリーンアップ/その他の問題に対処する必要があります)。

10
David Spillett