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