Bug #85997 inplace alter table with foreign keys causes table definition mismatch
Submitted: 19 Apr 2017 8:17 Modified: 1 Feb 2018 13:14
Reporter: Magnus Blåudd Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Data Dictionary Severity:S2 (Serious)
Version:8.0.2 OS:Any
Assigned to: CPU Architecture:Any

[19 Apr 2017 8:17] Magnus Blåudd
Description:
When doing an inplace alter table with foreign keys the table definition for the table which is not properly updated to reflect what is stored in the DD of the MySQL Server doing the alter. This problem occurs since the "table_def" parameter provided to handler::ha_inplace_alter_table() does not include all the properties (especially foreign keys and triggers) of the completely altered table.

Looking at the code in mysql_inplace_alter_table() it's clear that the DD is modified with additional information after the call to handler::inplace_alter_table().

This problem affect inplace alter table of table with foreign keys in NDB.

How to repeat:
Looking at the call sequence in mysql_inplace_alter_table() it goes like this:

  ha_prepare_inplace_alter_table(altered_table_def)
     - ndbcluster will start schema transaction
     - ndbcluster will prepare the alter

  ha_inplace_alter_table(altered_table_def)
    - ndbcluster will save the serialized(altered_table_def)
    - and alter the table in NDB
    - ndbcluster will commit schema transaction
     
  ha_commit_inplace_alter_table()
    - ndbcluster will prepare the alter on the other mysqld(s)

  dd::store(altered_table_def)

  dd::add_foreign_keys_and_triggers()
    - this modifies the DD with additional information
      which has not been provided earlier.

  ha_notify_table_changed()
    - !!ndbcluster would need to start a new schema transaction and alter the table
      again in order to save the correct serialized table definition. This is the problem!!!
    - ndbcluster will commit the alter on the other mysqld(s)
      and they will read the serialized table_def from NDB to update
      their DD 

Suggested fix:
Provide full table definition of altered table in ha_inplace_alter_table(). It might be possible to move the logic which alters the table in NDB so that it's enough if the complete table_def is provided in ha_commit_inplace_alter_table(). But ha_notify_table_changed() is too late and should in my opinion not really have to do anything with the inplace alter table protocol.
[1 Feb 2018 13:14] Daniel Price
Posted by developer:
 
Fixed as of the upcoming 8.0.5, 9.0.0 release, and here's the changelog entry:

An in-place ALTER TABLE operation on a table with foreign keys resulted
in a table definition mismatch. The new table definition passed to storage
engine methods during the ALTER TABLE execution contained invalid foreign
key names.