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:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version: OS:Any
Assigned to: CPU Architecture:Any

[9 Jun 17:53] OCA Admin
Description:
This bug tracks a contribution by Przemysław Skibiński (Github user: inikep), as described in http://github.com/mysql/mysql-server/pull/667

How to repeat:
See description

Suggested fix:
See contribution code attached
[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.