InnoDB
の自動インクリメント処理の元の実装では、ステートメントベースレプリケーションや特定のリカバリシナリオでバイナリログを使用すると発生する問題を回避するために、次のような方針が使用されています。
InnoDB
テーブルに AUTO_INCREMENT
カラムを指定すると、InnoDB
データディクショナリ内のテーブルハンドルに、カラムに新しい値を割り当てる際に使用される自動インクリメントカウンタと呼ばれる特別なカウンタが含まれます。このカウンタは、ディスク上には格納されず、メインメモリー内にのみ格納されます。
InnoDB
では、ai_col
という名前の AUTO_INCREMENT
カラムを含むテーブル t
に自動インクリメントカウンタを初期化するために、次のようなアルゴリズムが使用されます。サーバーの起動のあとで、テーブル t
への最初の挿入をするために、InnoDB
は次のステートメントと同等なものを実行します。
SELECT MAX(ai_col) FROM t FOR UPDATE;
InnoDB
は、ステートメントで取得された値を増分し、それをテーブルのカラムおよび自動インクリメントカウンタに割り当てます。デフォルトでは、値が 1 ずつ増分されます。このデフォルトは、auto_increment_increment
構成の設定でオーバーライドできます。
テーブルが空の場合、InnoDB
では値 1
が使用されます。このデフォルトは、auto_increment_offset
構成の設定でオーバーライドできます。
自動インクリメントカウンタが初期化される前に、SHOW TABLE STATUS
ステートメントで t
テーブルが調査される場合は、InnoDB
によって値は初期化されますが、増分されず、後続の挿入で使用するために格納されます。この初期化では、テーブル上で通常の排他ロック読み取りが使用され、そのロックはトランザクションの最後まで存続します。
InnoDB
は、新たに作成されたテーブル用に自動インクリメントカウンタを初期化するときと同じ手順に従います。
自動インクリメントカウンタが初期化されたあとに、AUTO_INCREMENT
カラムの値を明示的に指定しない場合は、InnoDB
によってカウンタが増分され、新しい値がカラムに割り当てられます。カラム値を明示的に指定する行を挿入するときに、その値が現在のカウンタ値よりも大きい場合は、カウンタが指定されたカラム値に設定されます。
ユーザーが INSERT
で AUTO_INCREMENT
カラムに NULL
または 0
を指定すると、InnoDB
では、値が指定されなかった場合と同様にその行が処理され、新しい値が生成されます。
カラムに負の値を割り当てる場合や、値が指定された整数型に格納できる最大整数よりも大きくなる場合は、自動インクリメントメカニズムの動作が定義されません。
自動インクリメントカウンタにアクセスするときに、InnoDB
では、トランザクションの最後までではなく、現在の SQL ステートメントの最後まで存続する特別なテーブルレベルの AUTO-INC
ロックが使用されます。AUTO_INCREMENT
カラムを含むテーブルへの挿入の並列性を改善するために、特別なロック解放方針が導入されました。それにもかかわらず、2 つのトランザクションが同時に AUTO-INC
ロックを同じテーブル上で持つことはできません。これにより、AUTO-INC
ロックが長時間保持されると、パフォーマンスが影響を受ける可能性があります。これは、あるテーブルから別のテーブルにすべての行を挿入する INSERT INTO t1 ... SELECT ... FROM t2
などのステートメントの場合に発生する可能性があります。
InnoDB
では、サーバーが実行されていれば、インメモリーの自動インクリメントカウンタが使用されます。前に説明したように、サーバーが停止して再起動されると、テーブルへの最初の INSERT
時に、InnoDB
によってテーブルごとにカウンタが再初期化されます。
サーバーが再起動されると、CREATE TABLE
および ALTER TABLE
ステートメントの AUTO_INCREMENT =
テーブルオプションの効果も取り消されます。このオプションを N
InnoDB
テーブルで使用すると、初期のカウンタの値を設定したり、現在のカウンタ値を変更したりできます。
カウンタを使用して数値が生成されたトランザクションをロールバックすると、AUTO_INCREMENT
カラムに割り当てられた一連の値でギャップが見つかることがあります。