InnoDB
の自動インクリメント処理の元の実装では、バイナリログを使ってステートメントベースのレプリケーションや特定の復旧シナリオを実施する際に発生する問題を回避するために、次のような方針を採用しています。
もし InnoDB
テーブルに
AUTO_INCREMENT
カラムを指定すると、InnoDB
データ辞書内のテーブルハンドルは、カラムに新しい値を割り当てるのに利用される自動インクリメントカウンタと呼ばれる特別なカウンタを含みます。このカウンタは、ディスク上には格納されず、主メモリー内だけに格納されます。
InnoDB
は、ai_col
という名前の
AUTO_INCREMENT
カラムを含むテーブル
t
に自動インクリメントカウンタを初期化するために、次のようなアルゴリズムを利用します。サーバーの起動のあとで、テーブル
t
への最初の挿入をするために、InnoDB
は次のステートメントと同等なものを実行します:
SELECT MAX(ai_col) FROM t FOR UPDATE;
InnoDB
はステートメントによって値が取り出されたものによってインクリメントし、それをカラムとテーブルの自動インクリメントカウンタに割り当てます。もしテーブルが空だったら、InnoDB
は値 1
を利用します。もしユーザーがテーブル
t
のための出力を表示する
SHOW TABLE STATUS
ステートメントを呼び出し、自動インクリメントカウンタがまだ初期化されていなかったら、InnoDB
は値を初期化するがインクリメントはせず、そしてそれをあとで挿入に利用するために格納します。この初期化はテーブル上で通常の排他ロック読み込みを利用し、そのロックはトランザクションの最後まで続きます。
InnoDB
は、作成されたばかりのテーブルのために自動インクリメントカウンタを初期化するのと同じ手順に従います。
自動インクリメントカウンタが初期化されたあと、もしユーザーが
AUTO_INCREMENT
カラムの値を明示的に指定しなければ、InnoDB
はカウンタを 1
でインクリメントしカラムに新しい値を割り当てます。もしユーザーがカラム値を明示的に指定する行を挿入し、それが現在のカウンタ値よりも大きければ、カウンタは指定されたカラムに設定されます。
自動インクリメントカウンタにアクセスするとき、InnoDB
は、トランザクションの最後までではなく、現在の
SQL
ステートメントの最後まで続く、特別なテーブルレベル
AUTO-INC
ロックを利用します。AUTO_INCREMENT
カラムを含んでいるテーブルへの挿入の並行処理を向上させるために、特別ロックリリース戦略が紹介されました。それにもかかわらず、2
つのトランザクションは
AUTO-INC
ロックが長時間保持されればパフォーマンスインパクトを与えることができる
AUTO-INC
ロックを同じテーブル上で同時に持つことができません。これは、1
つのテーブルからすべての行を別のテーブルに挿入する
INSERT INTO t1 ... SELECT ... FROM
t2
のようなステートメントのような場合のことです。
InnoDB
はサーバーが起動しているかぎり、メモリー内の自動インクリメントカウンタを利用します。サーバーが停止し再起動したとき、先ほど説明があったように、InnoDB
は、テーブルへの最初の
INSERT
に対する各テーブルのカウンタを再初期化します。
もしカウンタを利用して生成された数値を持つトランザクションをロールバックすると、AUTO_INCREMENT
に割り当てられた値のシーケンス内のギャップに気がつくでしょう。
もしユーザーが NULL
か 0
を
INSERT
内の
AUTO_INCREMENT
カラムに指定すると、InnoDB
は、値が指定されず、新しい値も生成されていないかのように行を扱います。
自動インクリメント構造の性能は、もしユーザーがカラムにマイナスの値を割り当てたり、もし値が指定した整数型内に格納することができる最大値を上回っていたりすると、定義できません。
AUTO_INCREMENT
カラムは、InnoDB
テーブル上のあるインデックスの最初のカラムとして指定されている必要があります。
InnoDB
は、初期カウンタ値を設定したり、現在のカウンタ値を変更するために、CREATETABLE
と ALTERTABLE
ステートメント内の
AUTO_INCREMENT=
テーブルオプションをサポートします。この節の最初の方で説明があったとおり、このオプションの効果はサーバーの再起動によって無くなってしまいます。
N