Skip to content
/ server Public

Comments

MDEV-37886 PAGE_COMPRESSED ALTER TABLE operations inconsistent with innodb_file_per_table setting#4646

Merged
dr-m merged 1 commit into10.6from
MDEV-37886
Feb 18, 2026
Merged

MDEV-37886 PAGE_COMPRESSED ALTER TABLE operations inconsistent with innodb_file_per_table setting#4646
dr-m merged 1 commit into10.6from
MDEV-37886

Conversation

@Thirunarayanan
Copy link
Member

Problem:

InnoDB DDL does ALTER TABLE PAGE_COMPRESSED=1 because:

  1. check_if_supported_inplace_alter() reads srv_file_per_table during precheck and does allow INSTANT operation.
  2. User does change innodb_file_per_table later. But prepare phase read srv_file_per_table again during execution.
  3. If the global variable changed between these phases, causes server abort for page_compressed tables.

Solution:

  • Add a file_per_table member to Alter_inplace_info to capture the innodb_file_per_table value during the precheck phase and use that consistent value throughout the entire ALTER TABLE operation.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@Thirunarayanan Thirunarayanan force-pushed the MDEV-37886 branch 2 times, most recently from c20173a to 1b225b6 Compare February 13, 2026 10:38
sql/handler.h Outdated
Comment on lines 2636 to 2648
/** true for ALTER IGNORE TABLE ... */
const bool ignore;

/** true for online operation (LOCK=NONE) */
bool online= false;
/** Online operation and storage engine specific flags */
struct
{
/** TRUE for online operation (LOCK=NONE) */
unsigned online : 1;
/** TRUE when innodb_file_per_table is set */
unsigned file_per_table : 1;
/** Reserved for future storage engine flags */
unsigned reserved : 6;
} engine_flags= {0, 0, 0};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be no need for the reserved field nor for the struct encapsulation.

Could the ignore flag be part of the same bit-field? Could we move this bit-field next to uint index_altered_ignorability_count in order to reduce the alignment loss? Check the output of ptype/o Alter_inplace_info in GDB.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{code}

Before:
======
(gdb) ptype /o ha_alter_info
type = class Alter_inplace_info {
                             public:
/*      0      |       8 */    HA_CREATE_INFO *create_info;
/*      8      |       8 */    Alter_info *alter_info;
/*     16      |       8 */    KEY *key_info_buffer;
/*     24      |       4 */    uint key_count;
/*     28      |       4 */    uint index_drop_count;
/*     32      |       8 */    KEY **index_drop_buffer;
/*     40      |       4 */    uint index_add_count;
/* XXX  4-byte hole      */
/*     48      |       8 */    uint *index_add_buffer;
/*     56      |       8 */    KEY_PAIR *index_altered_ignorability_buffer;
/*     64      |       4 */    uint index_altered_ignorability_count;
/* XXX  4-byte hole      */
/*     72      |      32 */    Rename_keys_vector rename_keys;
/*    104      |       8 */    inplace_alter_handler_ctx *handler_ctx;
/*    112      |       8 */    inplace_alter_handler_ctx **group_commit_ctx;
/*    120      |       8 */    alter_table_operations handler_flags;
/*    128      |       8 */    ulong partition_flags;
/*    136      |       8 */    partition_info * const modified_part_info;
/*    144      |       1 */    const bool ignore;
/*    145      |       1 */    bool online;
/* XXX  6-byte hole      */
/*    152      |       8 */    inplace_alter_table_commit_callback *inplace_alter_table_committed;
/*    160      |       8 */    void *inplace_alter_table_committed_argument;
/*    168      |       4 */    enum_alter_inplace_result inplace_supported;
/* XXX  4-byte hole      */
/*    176      |       8 */    const char *unsupported_reason;
/*    184      |       1 */    const bool error_if_not_empty;
/*    185      |       1 */    bool mdl_exclusive_after_prepare;
/* XXX  6-byte padding   */

                               /* total size (bytes):  192 */
                             } *
After:
=====
(gdb) ptype/o ha_alter_info
type = class Alter_inplace_info {
                             public:
/*      0      |       8 */    HA_CREATE_INFO *create_info;
/*      8      |       8 */    Alter_info *alter_info;
/*     16      |       8 */    KEY *key_info_buffer;
/*     24      |       8 */    KEY **index_drop_buffer;
/*     32      |       8 */    uint *index_add_buffer;
/*     40      |       8 */    KEY_PAIR *index_altered_ignorability_buffer;
/*     48      |       8 */    inplace_alter_handler_ctx *handler_ctx;
/*     56      |       8 */    inplace_alter_handler_ctx **group_commit_ctx;
/*     64      |       8 */    alter_table_operations handler_flags;
/*     72      |       8 */    partition_info * const modified_part_info;
/*     80      |       8 */    inplace_alter_table_commit_callback *inplace_alter_table_committed;
/*     88      |       8 */    void *inplace_alter_table_committed_argument;
/*     96      |       8 */    const char *unsupported_reason;
/*    104      |       8 */    ulong partition_flags;
/*    112      |      32 */    Rename_keys_vector rename_keys;
/*    144      |       4 */    uint key_count;
/*    148      |       4 */    uint index_drop_count;
/*    152      |       4 */    uint index_add_count;
/*    156      |       4 */    uint index_altered_ignorability_count;
/*    160      |       4 */    enum_alter_inplace_result inplace_supported;
/*    164: 0   |       4 */    unsigned int online : 1;
/*    164: 1   |       4 */    unsigned int file_per_table : 1;
/*    164: 2   |       4 */    unsigned int ignore : 1;
/*    164: 3   |       4 */    unsigned int error_if_not_empty : 1;
/*    164: 4   |       4 */    unsigned int mdl_exclusive_after_prepare : 1;
/* XXX  3-bit padding    */
/* XXX  3-byte padding   */

                               /* total size (bytes):  168 */
                             } *

…nnodb_file_per_table setting

Problem:
=======
InnoDB DDL does ALTER TABLE PAGE_COMPRESSED=1 because:
1. check_if_supported_inplace_alter() reads srv_file_per_table
during precheck and does allow INSTANT operation.
2. User does change innodb_file_per_table later.
But prepare phase read srv_file_per_table again during execution.
3. If the global variable changed between these phases, causes
server abort for page_compressed tables.

Solution:
=========
- Add a file_per_table member to Alter_inplace_info to
capture the innodb_file_per_table value during the
precheck phase and use that consistent value throughout
the entire ALTER TABLE operation.
- Converted boolean flags (online, ignore, error_if_not_empty,
mdl_exclusive_after_prepare) from individual boolean
members to bitfields packed in a single byte
- Reduced Alter_inplace_info structure size by 24 bytes
@dr-m dr-m merged commit 8882f8f into 10.6 Feb 18, 2026
12 of 13 checks passed
@dr-m dr-m deleted the MDEV-37886 branch February 18, 2026 07:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants