Requirement =========== It should be possible to replicate a table that has more columns on the master than on the slave, i.e., there are M columns in the table on the master and N columns in the table on the slave and M > N. When replicating in this manner, the contents of the extra columns on the master is lost, but replication will accept the situation and keep running. Implementation ============== Slave needs to discard columns that are not part of the slave table definition. Restrictions ============ All extra columns on master is at the end of the table. Related work ============ This work is related to WL#3259 (RBR with more columns on slave than on master) in that implementation of this worklog is necessary to support on-line table definition changes (a.k.a., "schema upgrade") when using circular replication. ---------------------------------------------------------------------------- Below is for reference only, not part of this WL. CONFIGURATION - Add "CHANGE MASTER SET SLAVE_IGNORE_EXTRA_COLUMNS=true" (and internally add corresponding variable to mi) OFFICIAL DESCRIPTION Ability to introduce new columns without impacting ongoing traffic. This is required to introduce new attributes to existing tables. There will only be the ability to add columns in this first release. Add column is only possible on “dynamic tables”. Starting with NDB-6.1.7, tables are dynamic by default (NDB-6.1.6 tables are not). Please note that it is only possible to add columns at the end of a table and still maintain compatibility. Online disk-based columns are not supported. New columns must have default values, or the replication stream needs to be synchronized by the DBA with the change. Effects and behavior of this feature to replication in multi-master mode must be considered. DDL changes will not be replicated, instead individually applied. Support for replicating to and from tables with more or less columns will be supported. • Master (T) replicating to Slave (T+1) • Master (T+1) replicating to Slave (T) NOT NULL columns should have a default value assigned to them when replicating. For restore using ndb_restore, schemas must be the same, ndb_restore cannot handle adding columns.
The basic constraint of this work is that a number of additional columns on slave can appear at the end of the table definition. This is what application must respect because the slave server's replication code does not check whether that's true or not. This feature does not affect statement-based replication at all. Master side =========== The master should deliver necessary info about the extra fields the slave is to skip when it parses a row. That info should be sent to the slave per table basis for efficiency. The master should deliver necessary info for the slave to be able to decide whether a nullable extra column has any data or the data is NULL and thereafter the values is presented an a turned-ON null bit. Slave side ========== the slave must be able to discard all data corresponding the extra columns to satisfy the basic constraint like to reach the end of the event's data upon passing though skipping algorithm. The skipping algorithm must be robust to work with any type of replication events on any type of tables incl NDB, whose events carry only modified columns.
Changes to ``unpack_row()`` =========================== Changes in unpack_row should take care of stopping fields unpacking when slave's version of the record got filled up "prematurely". I.e the main loop of unpacking of regular fields continuation condition should be refined and no work for filling slave's extra columns is needed (by this task definition). Such simplistic approach bases on either ability (feasibility) of instantiating of a Field class given the type of the field delivered with Table map event or on a non-existed yet info on the size of an individual row in Rows_log_event chunk. In the former case, to skip the extra masters columns would be done via calling Field::unpack(); in the latter, to skip it would be simply ignore the trailing part starting from the last common field unpacking addvanced pointer till the value of the size of the row. last common master's row field unpacking length | | +--------------------+-------------------+ | | Extra fields | | | on master | +--------------------+-------------------+ There is the third alternative to exploit `field_length_from_packed'. That'd an light equivalent to the instantiation. This solution was chosen for implementation where the function above was replaced by table_def::get_field_size() provided by WL#3228. To unpack a nullable extra column which value is NULL it's necessary to know the value of field::maybe_null(). That info is per-table and is included as part of additional information to be sent by the master for WL#3228. The extra columns skipping alg is as the following At the end of the regular columns unpacking loop the last field counter is stored. In the loop starting from the counter + 1 all the extra columns are processed to advance unpack_row():pack_ptr in the column presented in Rows_log_event m_cols bitmap respecting possible absence of the value for a nullable column: if (!((null_bits & null_mask) && tabledef->maybe_null(i))) pack_ptr+= tabledef->get_field_size(i, (uchar *) pack_ptr); The caller has a guard checking how well the final pack_ptr value fits to the end of the event's data in the end.