Skip to content

PS-9616 [8.4] Inconsistent DDL behaviour for ALTER TABLE with INPLACE/INSTANT - #5927

Open
catalinbp wants to merge 1 commit into
percona:8.4from
catalinbp:ps-9616
Open

PS-9616 [8.4] Inconsistent DDL behaviour for ALTER TABLE with INPLACE/INSTANT#5927
catalinbp wants to merge 1 commit into
percona:8.4from
catalinbp:ps-9616

Conversation

@catalinbp

@catalinbp catalinbp commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

PS-9616 [8.4] Inconsistent DDL behaviour for ALTER TABLE with INPLACE/INSTANT
https://perconadev.atlassian.net/browse/PS-9616

Changing the COLLATE attribute of a non-indexed column (and/or the
table's default COLLATE) is a metadata-only change: the stored bytes
are unchanged and, since the column is not indexed, no index reordering
is required. InnoDB, however, handled these operations inconsistently.

INPLACE: when the column COLLATE change and the table-level COLLATE=
change were issued in a single ALTER statement, InnoDB switched to
rebuilding the table even though a rebuild is unnecessary. The
algorithm-selection checks only recognised CHANGE_CREATE_OPTION on its
own and did not account for ALTER_COLUMN_EQUAL_PACK_LENGTH being present
at the same time. Fix the checks in innobase_need_rebuild() and in the
prepare/inplace phases to mask out ALTER_COLUMN_EQUAL_PACK_LENGTH as
well, so the combined statement is done in-place without a rebuild.
Indexed columns are unaffected: they set ALTER_STORED_COLUMN_TYPE
instead of ALTER_COLUMN_EQUAL_PACK_LENGTH and continue to be rejected
("Cannot change column type").

INSTANT: the same metadata-only changes were rejected under
ALGORITHM=INSTANT even though they touch no data.
ha_innobase::check_if_supported_inplace_alter() now reports
HA_ALTER_INPLACE_INSTANT when the only handler flags are a subset of
{ALTER_COLUMN_EQUAL_PACK_LENGTH, CHANGE_CREATE_OPTION} and the change
needs no rebuild (innobase_need_rebuild() is false, which already
excludes ROW_FORMAT, KEY_BLOCK_SIZE and TABLESPACE changes).

Crucially this does NOT set handler_trivial_ctx, so is_instant() stays
false and the regular no-rebuild commit path runs (commit_get_autoinc /
commit_try_norebuild / innobase_rename_or_enlarge_columns_cache). That
path correctly updates the in-memory column metadata (length/charset),
AUTO_INCREMENT and other CREATE OPTIONs. The instant commit executor
(commit_instant_ddl) is built only for genuine no-change / rename /
virtual / add-drop-column cases and must not be used here, as it would
skip those fix-ups (e.g. leaving col->len stale and tripping the rem0rec
length assertion, or ignoring AUTO_INCREMENT=). Reporting INSTANT while
executing in-place is explicitly sanctioned by the SQL layer, which
treats HA_ALTER_INPLACE_INSTANT and HA_ALTER_INPLACE_NO_LOCK
identically. Partitioned tables are covered automatically:
ha_innopart::check_if_supported_inplace_alter() delegates to the
ha_innobase implementation for the non-instant case.

@catalinbp
catalinbp requested a review from dlenev April 24, 2026 09:59
@catalinbp

Copy link
Copy Markdown
Contributor Author

@catalinbp

catalinbp commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@catalinbp

catalinbp commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@catalinbp
catalinbp changed the base branch from trunk to 8.4 June 30, 2026 09:15
@catalinbp catalinbp changed the title PS-9616 [9.x] Inconsistent DDL behaviour for ALTER TABLE with INPLACE PS-9616 [8.4] Inconsistent DDL behaviour for ALTER TABLE with INPLACE/INSTANT Jun 30, 2026
…/INSTANT

https://perconadev.atlassian.net/browse/PS-9616

Changing the COLLATE attribute of a non-indexed column (and/or the
table's default COLLATE) is a metadata-only change: the stored bytes
are unchanged and, since the column is not indexed, no index reordering
is required. InnoDB, however, handled these operations inconsistently.

INPLACE: when the column COLLATE change and the table-level COLLATE=
change were issued in a single ALTER statement, InnoDB switched to
rebuilding the table even though a rebuild is unnecessary. The
algorithm-selection checks only recognised CHANGE_CREATE_OPTION on its
own and did not account for ALTER_COLUMN_EQUAL_PACK_LENGTH being present
at the same time. Fix the checks in innobase_need_rebuild() and in the
prepare/inplace phases to mask out ALTER_COLUMN_EQUAL_PACK_LENGTH as
well, so the combined statement is done in-place without a rebuild.
Indexed columns are unaffected: they set ALTER_STORED_COLUMN_TYPE
instead of ALTER_COLUMN_EQUAL_PACK_LENGTH and continue to be rejected
("Cannot change column type").

INSTANT: the same metadata-only changes were rejected under
ALGORITHM=INSTANT even though they touch no data.
ha_innobase::check_if_supported_inplace_alter() now reports
HA_ALTER_INPLACE_INSTANT when the only handler flags are a subset of
{ALTER_COLUMN_EQUAL_PACK_LENGTH, CHANGE_CREATE_OPTION} and the change
needs no rebuild (innobase_need_rebuild() is false, which already
excludes ROW_FORMAT, KEY_BLOCK_SIZE and TABLESPACE changes).

Crucially this does NOT set handler_trivial_ctx, so is_instant() stays
false and the regular no-rebuild commit path runs (commit_get_autoinc /
commit_try_norebuild / innobase_rename_or_enlarge_columns_cache). That
path correctly updates the in-memory column metadata (length/charset),
AUTO_INCREMENT and other CREATE OPTIONs. The instant commit executor
(commit_instant_ddl) is built only for genuine no-change / rename /
virtual / add-drop-column cases and must not be used here, as it would
skip those fix-ups (e.g. leaving col->len stale and tripping the rem0rec
length assertion, or ignoring AUTO_INCREMENT=). Reporting INSTANT while
executing in-place is explicitly sanctioned by the SQL layer, which
treats HA_ALTER_INPLACE_INSTANT and HA_ALTER_INPLACE_NO_LOCK
identically. Partitioned tables are covered automatically:
ha_innopart::check_if_supported_inplace_alter() delegates to the
ha_innobase implementation for the non-instant case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant