PS-9616 [8.4] Inconsistent DDL behaviour for ALTER TABLE with INPLACE/INSTANT - #5927
Open
catalinbp wants to merge 1 commit into
Open
PS-9616 [8.4] Inconsistent DDL behaviour for ALTER TABLE with INPLACE/INSTANT#5927catalinbp wants to merge 1 commit into
catalinbp wants to merge 1 commit into
Conversation
Contributor
Author
Contributor
Author
Contributor
Author
|
Also ASAN run for main and innodb suite: https://ps80.cd.percona.com/view/8.4/job/percona-server-8.4-ASAN-pipeline-parallel-mtr/19/ |
…/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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.