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.