Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41694

Read view after DDL returns wrong data when the table definition was reloaded

    XMLWordPrintable

Details

    • 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:

      1. Create table t, insert (1,1,1),(2,2,2), and start a read view in another connection.
      2. Run UPDATE t SET b = b + 10, then the DDL.
      3. 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.
      4. 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

          Activity

            People

              marko Marko Mäkelä
              alessandro.vetere Alessandro Vetere
              Alessandro Vetere Alessandro Vetere
              Marko Mäkelä Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Time Tracking

                  Estimated:
                  Original Estimate - 1d
                  1d
                  Remaining:
                  Time Spent - 5h Remaining Estimate - 3h
                  3h
                  Logged:
                  Time Spent - 5h Remaining Estimate - 3h
                  5h

                  Git Integration

                    Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.