Description:
The node recovery algorithm is missing a version check for tables in the ALTER_TABLE_COMMITTED state (as opposed to the TABLE_ADD_COMMITTED state which has the version check).
This can cause inconsistent schema across nodes after node recovery:
1. Table A is in altered state.
2. Node w shuts down/fails.
3. While node 2 is down, table A is altered again.
4. When node 2 recovers, it uses the old definition for A, while node 1 uses the new, correct definition.
How to repeat:
In a compiled tree:
$ perl mysql-test-run.pl --start-and-exit ndb_basic
Servers started, exiting
$ ../client/mysql --socket=var/tmp/master.sock -uroot test
mysql> create table a(a int primary key) engine=ndb;
mysql> alter table a rename to b;
mysql> exit
$ ../storage/ndb/tools/ndb_show_tables
id type state logging database schema name
3 UserTable Online Yes cluster def NDB$BLOB_2_3
6 OrderedIndex Online No sys def PRIMARY
1 SystemTable Online Yes sys def NDB$EVENTS_0
5 UserTable Online Yes test def b
2 UserTable Online Yes cluster def schema
4 UserTable Online Yes cluster def apply_status
0 SystemTable Online Yes sys def SYSTAB_0
0 IndexTrigger Online - NDB$INDEX_6_CUSTOM
$ ../storage/ndb/src/mgmclient/ndb_mgm -e '2 stop'
Connected to Management Server at: localhost:9310
Node 2: Node shutdown initiated
Node 2: Node shutdown completed.
Node 2 has shutdown.
$ ../storage/ndb/src/mgmclient/ndb_mgm -e '2 status'
Connected to Management Server at: localhost:9310
Node 2: not connected
$ ../client/mysql --socket=var/tmp/master.sock -uroot test
mysql> alter table b rename to c;
mysql> exit
$ ../storage/ndb/tools/ndb_show_tables
id type state logging database schema name
3 UserTable Online Yes cluster def NDB$BLOB_2_3
6 OrderedIndex Online No sys def PRIMARY
1 SystemTable Online Yes sys def NDB$EVENTS_0
5 UserTable Online Yes test def c
2 UserTable Online Yes cluster def schema
4 UserTable Online Yes cluster def apply_status
0 SystemTable Online Yes sys def SYSTAB_0
0 IndexTrigger Online - NDB$INDEX_6_CUSTOM
$ (cd var/ndbcluster-9310/ && ../../../storage/ndb/src/kernel/ndbd --no-defaults --core --character-sets-dir=../../../sql/share/charsets)
$ ../storage/ndb/src/mgmclient/ndb_mgm -e '2 status'
Connected to Management Server at: localhost:9310
Node 2: started (Version 5.1.12)
knielsen@ymer:/usr/local/mysql/mysql-5.1-tst/mysql-test$ ../storage/ndb/src/mgmclient/ndb_mgm -e '1 stop'
Connected to Management Server at: localhost:9310
Node 1: Node shutdown initiated
Node 1: Node shutdown completed.
Node 1 has shutdown.
$ ../storage/ndb/src/mgmclient/ndb_mgm -e '1 status'
Connected to Management Server at: localhost:9310
Node 1: not connected
$ ../storage/ndb/tools/ndb_show_tables
id type state logging database schema name
3 UserTable Online Yes cluster def NDB$BLOB_2_3
6 OrderedIndex Online No sys def PRIMARY
1 SystemTable Online Yes sys def NDB$EVENTS_0
5 UserTable Online Yes test def b
2 UserTable Online Yes cluster def schema
4 UserTable Online Yes cluster def apply_status
0 SystemTable Online Yes sys def SYSTAB_0
0 IndexTrigger Online - NDB$INDEX_6_CUSTOM
[after recovering node 2 and stopping node 1, we see that node 2 has the wrong definition, the table has the old name 'b', not the correct new name 'c'].
Suggested fix:
In the function Dbdict::checkSchemaStatus(), the case for state TABLE_ADD_COMMITTED has this version check:
if(newEntry->m_tableVersion == oldEntry->m_tableVersion)
A similar check is missing for state ALTER_TABLE_COMMITTED, and should be added.