InnoDB はマルチバージョニングのデータベースであるため、テーブルスペース内の古いバージョンのレコードに関する情報を保持しなければなりません。この情報は、ロールバックセグメントに格納されます。 ロールバックセグメントは Oracle のロールバックセグメントのデータ構造に似ています。
InnoDB は内部的に、データベースに格納されている各レコードに 2 つのフィールドを付加します。 6 バイトのフィールドには、レコードを最後に挿入または更新したトランザクションの識別子が記録されます(トランザクション ID)。削除も内部的には更新として扱われ、レコード内の特別なビットに削除済みとしてマークされます。各レコードには、ロールポインタと呼ばれる 7 バイトのフィールドも付加されます。ロールポインタは、ロールバックセグメントに書き込まれた取り消しログレコードを指します。レコードが更新された場合は、更新前のレコードの内容を再構築するために必要な情報が取り消しログレコードに記録されます。
InnoDB は、ロールバックセグメント内の情報を使用して、トランザクションのロールバックで必要な取り消し操作を実行します。また、読み取り一貫性のために、以前のバージョンのレコードを構築する場合にも、この情報が使用されます。
ロールバックセグメント内の UNDO ログは、挿入用の UNDO ログと更新用の UNDO ログに分かれています。挿入用の UNDO ログは、トランザクションロールバックにのみ必要で、トランザクションがコミットされると直ちに破棄されます。更新用の UNDO ログは、読み取り一貫性でも使用されるため、InnoDB がスナップショットを割り当てたトランザクションが存在しなくなるまで破棄できません。このようなトランザクションでは、読み取り一貫性で以前のバージョンのレコードを構築するために、更新用の UNDO ログの情報が必要となる場合があるからです。
トランザクションは定期的にコミットする必要があります。読み取り一貫性のある物のみを発行するトランザクションも同様です。 そうしないと、InnoDB が更新用 UNDO ログからデータを破棄できなくなり、ロールバックセグメントが大きくなって、テーブルスペースがいっぱいになるおそれがあります。
ロールバックセグメントにおける UNDO ログレコードの物理サイズは、通常、対応する挿入レコードまたは更新レコードよりも小さくなります。ロールバックセグメントに必要な領域を、これらのレコード長を使って、計算できます。
このマルチバージョニングの基本構想では、SQL ステートメントでレコードを削除しても、すぐにはそのレコードがデータベースから物理的に削除されません。 削除に対して書き込まれた更新取り消しログレコードを InnoDB が破棄できるようになった時点で、対応するレコードとそのインデックスレコードがデータベースから物理的に削除されます。この削除操作はパージと呼ばれます。この操作はきわめて高速で、通常は削除を行った SQL ステートメントと同程度の時間しかかかりません。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.