Details
-
Bug
-
Status: In Review (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3
-
None
-
Unexpected results
-
Q4/2026 Server Maintenance
Description
This was discovered during AI-assisted review of MDEV-41669.
There is a gap in InnoDB handling of MVCC+DDL when the table definition is evicted and reloaded.
Please see below the AI-generated description, which I agree with:
dict_index_t::trx_id is the ID of the transaction that created the index, and row_merge_is_index_usable() uses it to reject an index that is newer than the read view of the transaction. With this check, an old read view gets ER_TABLE_DEF_CHANGED after DDL replaces the data of the table.
dict_index_t::trx_id exists only in memory. When dict_sys_t::evict_table_LRU() evicts the table from the InnoDB data dictionary cache, dict_load_indexes() loads it again with trx_id 0. An old read view can then use the replaced indexes. It does not get an error, and it reads wrong data.
How to repeat
Test innodb.mvcc_ddl_evict (attached) does these steps for each case:
- Create table t, insert (1,1,1),(2,2,2), and start a read view in another connection.
- Run UPDATE t SET b = b + 10, then the DDL.
- Evict t: create 450 tables, run FLUSH TABLES, and wait until the master thread has evicted at least 40 tables, with table_definition_cache=400.
- Read t in the old read view.
Results in the old read view after eviction:
| DDL | Without eviction | After eviction |
|---|---|---|
| ALTER TABLE t FORCE, ALGORITHM=COPY | ER_TABLE_DEF_CHANGED | (1,11,1),(2,12,2) |
| ALTER TABLE t FORCE, ALGORITHM=INPLACE | ER_TABLE_DEF_CHANGED | (1,11,1),(2,12,2) |
| ALTER TABLE t ADD INDEX(b), then a read with FORCE INDEX(b) | ER_TABLE_DEF_CHANGED | empty result |
| TRUNCATE TABLE t | ER_TABLE_DEF_CHANGED | empty result |
| IMPORT TABLESPACE with and without .cfg | ER_TABLE_DEF_CHANGED | (1,11,1),(2,12,2) |
A correct read returns b = 1 and 2, or fails with ER_TABLE_DEF_CHANGED.
The master thread evicts tables when the number of tables in the cache is at least table_definition_cache. It seems that a server with many tables can therefore get the problem without special settings.
Fix
dict_load_indexes(): restore dict_index_t::trx_id from the DB_TRX_ID of the SYS_INDEXES record. Skip this for a discarded tablespace, because IMPORT TABLESPACE assigns the field.
ALTER TABLE ... RENAME INDEX also updates the SYS_INDEXES record. After eviction and reload, an old read view therefore gets ER_TABLE_DEF_CHANGED for a renamed index. Without eviction, the read view can still use the index.
The patch merges with no conflicts on 11.4, 11.8, 12.3 and 13.1. It was not tested on these branches.
Attachments
Issue Links
- relates to
-
MDEV-41669 ALTER TABLE…IMPORT TABLESPACE may break MVCC
-
- Closed
-