Description:
Since MySQL 8.0.29, InnoDB uses a "row versioning" mechanism to support
INSTANT ADD/DROP COLUMN. As part of this implementation, InnoDB performs a
max row size check during INSTANT DDL: it calculates the theoretical maximum
row size (assuming every column is filled to its maximum length) and rejects
the INSTANT DDL if this size exceeds the page record limit.
However, this check is overly conservative and causes practical problems:
1. **Upgrade compatibility regression**: In MySQL early 8.0 (before
8.0.29), INSTANT ADD COLUMN (the old implementation) did not have this
max row size restriction. After upgrading to 8.0.29+, tables that
previously allowed INSTANT ADD COLUMN may now be rejected, forcing users
to fall back to the much slower COPY/INPLACE algorithm. This is a
significant regression for users who relied on INSTANT DDL for large
tables in production.
2. **Theoretical vs. practical row size**: The check uses the theoretical
maximum row size, but in practice, rows rarely reach their maximum size.
For example, a table with many VARCHAR(255) or CHAR(200) columns will
almost never have all columns filled to their full length simultaneously.
The actual row size at DML time (INSERT/UPDATE) is already enforced by
InnoDB's "Record too big" check, which is sufficient to prevent
oversized records from being written to pages.
This contribution relaxes the restriction by introducing a new system
variable `innodb_instant_ddl_strict_row_size` (default ON for backward
compatibility):
- **ON** (default): Preserve the existing strict check. INSTANT DDL is
rejected if the theoretical max row size exceeds the page limit.
- **OFF**: Issue a warning but allow INSTANT DDL to proceed. The actual
row size enforcement is deferred to DML time — as long as the real
data fits within the page limit, the operation succeeds normally.
When the strict check is relaxed, a correctness issue arises during
rollback: after INSTANT ADD COLUMN, a record originally inserted at an
older row version (with fewer columns) may be updated and then rolled
back. If rollback rebuilds the record using current_row_version, the
restored record will include all INSTANT-added columns (filled with
default values), making it physically larger than the original. When the
theoretical max row size exceeds the page limit, this inflated record
may not fit in the page, causing the rollback to fail.
To solve this, this patch records the original row_version of each
record in the undo log during UPDATE/DELETE operations, and uses that
original version (instead of current_row_version) when rebuilding the
record during rollback and MVCC version construction. This ensures the
restored record contains only the columns visible at its original
version, maintaining the original compact physical format.
For records inserted before any INSTANT DDL (which have no version
flag in the record header), version 0 is written to the undo log,
representing the original table schema. During rollback, such records
are restored with the versioned bit set and version=0, so they are
interpreted using only the columns from the original table definition.
How to repeat:
N