| Bug #120649 | Contribution: InnoDB: crash recovery of unfinished ALTER TABLESPACE ENCRYPT ... | ||
|---|---|---|---|
| Submitted: | 9 Jun 17:53 | ||
| Reporter: | OCA Admin (OCA) | Email Updates: | |
| Status: | Open | Impact on me: | |
| Category: | MySQL Server: InnoDB storage engine | Severity: | S3 (Non-critical) |
| Version: | OS: | Any | |
| Assigned to: | CPU Architecture: | Any | |
[9 Jun 17:53]
OCA Admin
[9 Jun 17:53]
OCA Admin
Contribution submitted via Github - InnoDB: crash recovery of unfinished ALTER TABLESPACE ENCRYPTION re-binlogs the (*) Contribution by Przemysław Skibiński (Github inikep, https://github.com/mysql/mysql-server/pull/667): ### Summary InnoDB crash recovery can resume an unfinished `ALTER TABLESPACE … ENCRYPTION` operation by re-executing `ALTER TABLESPACE` through an internal startup background THD: ``` fsp_init_resume_alter_encrypt_tablespace() -> dd::alter_tablespace_encryption() -> execute_query() -> Sql_cmd_alter_tablespace::execute() ``` That THD is created by `create_internal_thd()`, which leaves session binlogging enabled. So the replay runs through the normal SQL DDL path and **emits a second binlog event and allocates a fresh GTID** for the original user DDL — which was already binlogged when the user issued it. Because this happens very early in startup, the replay''s in-flight commit on `mysql.ibd` races with GTID/binlog initialization and with the attachable transactions that open the DD and replication metadata tables, tripping debug assertions in GTID/binlog bookkeeping and startup DD access, e.g.: ``` Gtid_state::update_gtids_impl_own_gtid(): owned_gtids.is_owned_by(thd->owned_gtid, thd->thread_id()) executed_gtids.contains_gtid() Mutex_cond_array::get_max_index() THD::Attachable_trx::~Attachable_trx() checking transaction_rollback_request ``` The last assertion is the one for which the existing `component_keyring_file.mysql_ts_alter_encrypt_1` test is currently disabled under **Bug#29531106**. A slow keyring backend widens the race window, but the defect is in the replay itself, not the keyring backend. ### Fix Treat the recovery replay as local startup repair rather than a new user-visible DDL: - Disable session binlogging for the internal `dd::alter_tablespace_encryption()` replay (`Disable_binlog_guard`). - Skip the explicit `ALTER TABLESPACE` DDL binlog write only for startup background encryption replays (`system_thread == SYSTEM_THREAD_BACKGROUND` with an `ENCRYPTION` clause). - When `mysql.ibd` itself is among the spaces being rolled forward, wait for the resume thread to finish before startup opens DD and replication metadata tables. This prevents recovery from emitting a second binlog event or allocating a fresh GTID, while avoiding a broad change to normal `ALTER TABLESPACE` binlog behavior. ### Test New deterministic regression test `component_keyring_file.tablespace_encrypt_recover_gtid` that does not depend on slow keyring access. With `gtid_mode=ON` and binary logging enabled, it crashes in the middle of `ALTER TABLESPACE mysql ENCRYPTION=''Y''`, lets InnoDB crash recovery resume the encryption from the startup background THD, and asserts that the replay does not change `@@GLOBAL.gtid_executed`. * Without the fix, recovery crashes in `Gtid_state::update_gtids_impl_own_gtid()` (and otherwise the replay would grow `gtid_executed` by one). * With the fix, `gtid_executed` is unchanged and recovery completes cleanly. ### Verification ``` ./mysql-test-run.pl --suite=component_keyring_file tablespace_encrypt_recover_gtid --debug-server --big-test --retry=0 --force --parallel=1 ``` --- I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.
Contribution: git_patch_3832074210.txt (text/plain), 17.67 KiB.
