InnoDB
がマルチバージョン
ストレージ エンジンなので、それはテーブル
スペース内に古いバージョンの行についての情報を保管しておく必要があります。この情報は、rollback
segment
(Oracle内の類似データ構造の後)と呼ばれるデータ構造内に格納されます。
InnoDB
は内部的にデータベース内に格納された各行に2つのフィールドを追加します。6バイト
フィールドは、行を挿入または更新した最後のトランザクションに対して、トランザクション識別子を指示します。
また、行内の特別ビットが削除されたとマークするように設定されている点で、削除は内部的に更新として扱われます。各行は、ロール
ポインタと呼ばれる7バイトのフィールドも含んでいます。そのロール
ポインタは、ロールバック
セグメントに書かれた取り消しログレコードを指し示します。もし行が更新されると、取り消しログ
レコードは行の内容が更新される前に、それを再構築する為に必要な情報を含みます。
InnoDB
はトランザクション
ロールバック内で必要とされた取り消し操作を実行する為に、ロールバック
セグメント内の情報を利用します。それはまた、一貫した読み取りに対する行のこれまでのバージョンを構築する為の情報も利用します。
ロールバック
セグメント内の取り消しログは挿入と更新取り消しログに分割されます。挿入取り消しログはトランザクション
ロールバックの中でだけ必要であり、トランザクションがコミットしたらすぐに廃棄できます。更新取り消しログも一貫した読み取りの中で利用されますが、それらはトランザクションがなくなり、それに対して、一貫した読み取りの中でデータベース行のこれまでのバージョンを構築する為の更新取り消しログ内の情報を必要とするスナップショットを
InnoDB
が割り当てた後でだけ廃棄できます。
一貫した読み取りだけを発行するトランザクションを含み、トランザクションを定期的にコミットする事を覚えておく必要があります。そうでなければ、InnoDB
は更新取り消しログからデータを廃棄する事ができず、ロールバック
セグメントが大きく成長しすぎてテーブルスペースを一杯にしてしまいます。
ロールバック セグメント内の取り消しログ レコードの物質的サイズは、一般的にはそれに対応する挿入された、または更新された行よりも小さいです。ロールバック セグメントに必要な領域を計算する為にこの情報を利用する事ができます。
InnoDB
マルチ バージョン
スキーム内では、行はSQL
ステートメントで削除しても、データベースから即座に物理的に削除されません。InnoDB
が削除の為に書かれた更新取り消しログ
レコードを廃棄する事ができる時だけ、それはデータベースからそれに対応する行とそのインデックスを物理的に削除する事もできます。この削除操作はパージと呼ばれる大変早い操作で、通常削除を行った
SQL ステートメントと同じ時間順をとります。
ユーザがテーブル内で大体同じくらいの比率で小さめのバッチの行を挿入、削除するというようなシナリオでは、パージ
スレッドが遅れをとり始め、そしてテーブルが大きくなり続け、全てがディスクに頼った状態になり操作がとても遅くなる可能性があります。テーブルがたったの10MB
の有効データしか持っていないとしても、たくさんの
「停止した」 行が10GB
を占めるほどにまで大きくなる事があります。そのような場合は、新しい行操作を抑圧し、パージ
スレッドにもっと多くのリソースを割り当てるのが良いでしょう。innodb_max_purge_lag
システム変数は、まさにこの目的の為に存在します。詳細については、項13.5.4. 「InnoDB
起動オプションとシステム変数」
をご参照ください。