From: Gopal Shankar Date: June 11 2012 6:57am Subject: bzr push into mysql-trunk-wl6292 branch (gopal.shankar:3924 to 3925) WL#6292 List-Archive: http://lists.mysql.com/commits/144166 Message-Id: <201206110657.q5B6vZx4002217@acsmt357.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3925 Gopal Shankar 2012-06-11 WL#6292 - Make TIMESTAMP columns nullable by default. This patch contains, * Making use of new Relay_log_info::adapt_to_master_version(), that represent an interface to provide adapting the slave applier to master versions. This is provided by Andrei as part of, Bug#14162406 - INSUFFICIENT MASTER VERSION ADAPTATION INFRASTRUCTURE ON SLAVE With the above patch, the slave applier thread sets --explicit_default_for_timestamp ONLY when the master version is upgraded or downgraded, rather than per statement execution. modified: sql/log_event.cc sql/log_event.h sql/rpl_rli.cc sql/rpl_rli.h sql/rpl_rli_pdb.cc sql/rpl_rli_pdb.h sql/sql_parse.cc 3924 Gopal Shankar 2012-06-11 WL#6292 - Make TIMESTAMP columns nullable by default. This additional patch contains, * Fix comments from Jon Olav and Andrei. * Changes to MTR scripts to that they work fine with and without --explicit_defaults_for_timestamp set. * Changes to system tables in scripts. - mysql_system_tables_fix.sql - some more changes mysql_system_tables.sql. * Move non-repl test from wl6292.test to type_timestamp.test. * Retain SHOW TABLE display 'NULL' for TIMESTAMP. added: mysql-test/t/type_timestamp-master.opt modified: mysql-test/extra/rpl_tests/rpl_extra_col_slave.test mysql-test/include/ctype_numconv.inc mysql-test/include/function_defaults.inc mysql-test/include/function_defaults_notembedded.inc mysql-test/include/mix2.inc mysql-test/include/ps_create.inc mysql-test/include/select.inc mysql-test/r/create.result mysql-test/r/ctype_binary.result mysql-test/r/ctype_cp1251.result mysql-test/r/ctype_latin1.result mysql-test/r/ctype_ucs.result mysql-test/r/ctype_utf8.result mysql-test/r/function_defaults.result mysql-test/r/function_defaults_notembedded.result mysql-test/r/insert.result mysql-test/r/key.result mysql-test/r/metadata.result mysql-test/r/mix2_myisam.result mysql-test/r/multi_update.result mysql-test/r/mysqld--help-notwin.result mysql-test/r/mysqldump.result mysql-test/r/ps_1general.result mysql-test/r/ps_2myisam.result mysql-test/r/ps_3innodb.result mysql-test/r/ps_4heap.result mysql-test/r/ps_5merge.result mysql-test/r/select_all.result mysql-test/r/select_all_bka.result mysql-test/r/select_all_bka_nixbnl.result mysql-test/r/select_icp_mrr.result mysql-test/r/select_icp_mrr_bka.result mysql-test/r/select_icp_mrr_bka_nixbnl.result mysql-test/r/select_none.result mysql-test/r/select_none_bka.result mysql-test/r/select_none_bka_nixbnl.result mysql-test/r/show_check.result mysql-test/r/sql_mode.result mysql-test/r/strict.result mysql-test/r/type_datetime.result mysql-test/r/type_ranges.result mysql-test/r/type_temporal_fractional.result mysql-test/r/type_timestamp.result mysql-test/r/union.result mysql-test/r/wl6292.result mysql-test/suite/funcs_1/include/innodb_tb4.inc mysql-test/suite/funcs_1/include/memory_tb4.inc mysql-test/suite/funcs_1/include/myisam_tb4.inc mysql-test/suite/funcs_1/include/ndb_tb4.inc mysql-test/suite/funcs_1/r/innodb_func_view.result mysql-test/suite/funcs_1/r/is_columns_innodb.result mysql-test/suite/funcs_1/r/is_columns_memory.result mysql-test/suite/funcs_1/r/is_columns_myisam.result mysql-test/suite/funcs_1/r/memory_func_view.result mysql-test/suite/funcs_1/r/myisam_func_view.result mysql-test/suite/funcs_1/views/func_view.inc mysql-test/suite/innodb/r/innodb.result mysql-test/suite/innodb/t/innodb.test mysql-test/suite/rpl/include/rpl_partition.inc mysql-test/suite/rpl/r/rpl_extra_col_slave_innodb.result mysql-test/suite/rpl/r/rpl_extra_col_slave_myisam.result mysql-test/suite/rpl/r/rpl_function_defaults.result mysql-test/suite/rpl/r/rpl_innodb_bug28430.result mysql-test/suite/rpl/r/rpl_multi_engine.result mysql-test/suite/rpl/r/rpl_partition_archive.result mysql-test/suite/rpl/r/rpl_partition_innodb.result mysql-test/suite/rpl/r/rpl_partition_memory.result mysql-test/suite/rpl/r/rpl_partition_myisam.result mysql-test/suite/rpl/t/rpl_function_defaults.test mysql-test/suite/rpl/t/rpl_innodb_bug28430.test mysql-test/suite/rpl/t/rpl_multi_engine.test mysql-test/t/create.test mysql-test/t/insert.test mysql-test/t/key.test mysql-test/t/metadata.test mysql-test/t/multi_update.test mysql-test/t/mysqldump.test mysql-test/t/ps_4heap.test mysql-test/t/ps_5merge.test mysql-test/t/show_check.test mysql-test/t/sql_mode.test mysql-test/t/strict.test mysql-test/t/system_mysql_db_fix40123.test mysql-test/t/system_mysql_db_fix50030.test mysql-test/t/system_mysql_db_fix50117.test mysql-test/t/type_datetime.test mysql-test/t/type_ranges.test mysql-test/t/type_temporal_fractional.test mysql-test/t/type_timestamp.test mysql-test/t/union.test mysql-test/t/wl6292.test scripts/mysql_system_tables.sql scripts/mysql_system_tables_fix.sql sql/mysqld.cc sql/sql_insert.cc sql/sql_show.cc sql/sql_yacc.yy sql/sys_vars.cc === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2012-06-05 05:58:05 +0000 +++ b/sql/log_event.cc 2012-06-11 06:49:09 +0000 @@ -5562,22 +5562,6 @@ Format_description_log_event::do_shall_s #endif -inline void do_server_version_split(char* version, uchar split_versions[3]) -{ - char *p= version, *r; - ulong number; - for (uint i= 0; i<=2; i++) - { - number= strtoul(p, &r, 10); - split_versions[i]= (uchar) number; - DBUG_ASSERT(number < 256); // fit in uchar - p= r; - DBUG_ASSERT(!((i == 0) && (*r != '.'))); // should be true in practice - if (*r == '.') - p++; // skip the dot - } -} - /** Splits the event's 'server_version' string into three numeric pieces stored @@ -5598,12 +5582,6 @@ void Format_description_log_event::calc_ server_version_split[1], server_version_split[2])); } -inline ulong version_product(const uchar* version_split) -{ - return ((version_split[0] * 256 + version_split[1]) * 256 - + version_split[2]); -} - /** @return integer representing the version of server that originated the current FD instance. === modified file 'sql/log_event.h' --- a/sql/log_event.h 2012-06-06 09:52:35 +0000 +++ b/sql/log_event.h 2012-06-11 06:49:09 +0000 @@ -4937,6 +4937,28 @@ inline bool is_gtid_event(Log_event* evt evt->get_type_code() == ANONYMOUS_GTID_LOG_EVENT); } +inline ulong version_product(const uchar* version_split) +{ + return ((version_split[0] * 256 + version_split[1]) * 256 + + version_split[2]); +} + +inline void do_server_version_split(char* version, uchar split_versions[3]) +{ + char *p= version, *r; + ulong number; + for (uint i= 0; i<=2; i++) + { + number= strtoul(p, &r, 10); + split_versions[i]= (uchar) number; + DBUG_ASSERT(number < 256); // fit in uchar + p= r; + DBUG_ASSERT(!((i == 0) && (*r != '.'))); // should be true in practice + if (*r == '.') + p++; // skip the dot + } +} + /** @} (end of group Replication) */ === modified file 'sql/rpl_rli.cc' --- a/sql/rpl_rli.cc 2012-05-30 10:03:45 +0000 +++ b/sql/rpl_rli.cc 2012-06-11 06:49:09 +0000 @@ -130,6 +130,7 @@ Relay_log_info::Relay_log_info(bool is_s my_atomic_rwlock_init(&slave_open_temp_tables_lock); relay_log.init_pthread_objects(); + do_server_version_split(::server_version, slave_version_split); DBUG_VOID_RETURN; } @@ -2110,3 +2111,140 @@ bool Relay_log_info::write_info(Rpl_info DBUG_RETURN(FALSE); } + +/** + Delete the existing event and set a new one. This class is + responsible for freeing the event, the caller should not do that. + When a new FD is from the master adaptaion routine is invoked + to align the slave applier execution context with the master version. + + The method is run by SQL thread/MTS Coordinator. + Although notice that MTS worker runs it, inefficiently (see assert), + once at its destruction time. + todo: fix Slave_worker and Relay_log_info inheritance relation. +*/ + +void Relay_log_info::set_rli_description_event(Format_description_log_event *fdle) +{ + DBUG_ASSERT(!info_thd || !is_mts_worker(info_thd) || !fdle); + + if (fdle && (fdle->server_id != (uint32) ::server_id)) + { + adapt_to_master_version(fdle); + if (info_thd && is_parallel_exec()) + { + for (uint i= 0; i < workers.elements; i++) + { + Slave_worker *w= *(Slave_worker **) dynamic_array_ptr(&workers, i); + w->set_rli_description_event(fdle); + } + } + } + if (rli_description_event) + delete rli_description_event; + rli_description_event= fdle; +} + +/** + The method lists rules of adatation for the slave applier + to specific master versions. + It's executed right before a new master FD is set for + slave appliers execution context. + Comparison of the old and new version yields the adaptive + actions direction. +*/ +void Relay_log_info::adapt_to_master_version(Format_description_log_event *fdle) +{ + THD *thd=info_thd; + ulong master_version, current_version; + struct st_feature_version + { + /* + The enum must be in the version not-descending top-down order, + the last item formally corresponds to highest possible server + version (never reached, thereby no adapting actions here); + enumeration starts from zero. + */ + enum + { + WL6292_TIMESTAMP_EXPLICIT_DEFAULT= 0, + _END_OF_LIST // always last + } item; + uchar version_split[3]; + } features[]= + { + // order is the same as in the enum + { st_feature_version::WL6292_TIMESTAMP_EXPLICIT_DEFAULT, + {5, 6, 6} }, // TODO: fix the minor number!!! + + { st_feature_version::_END_OF_LIST, + {255, 255, 255} } + }; + int changed= !fdle ? 0 : + (master_version= fdle->get_version_product()) - + (current_version= rli_description_event->get_version_product()); + + /* When the last version is not changed nothing to adapt for */ + if (!changed) + return; + + /* + find item starting from and ending at for which adaptive actions run + for downgrade or upgrade branches. + (todo: convert into bsearch when number of features will grow significantly) + */ + bool downgrade= changed < 0; + long i, i_0= st_feature_version::_END_OF_LIST, i_1= i_0; + + for (i= 0; i < st_feature_version::_END_OF_LIST; i++) + { + ulong ver_f= version_product(features[i].version_split); + + if ((downgrade ? master_version : current_version) < ver_f && + i_0 == st_feature_version::_END_OF_LIST) + i_0= i; + if ((downgrade ? current_version : master_version) < ver_f) + { + i_1= i; + DBUG_ASSERT(i_1 >= i_0); + break; + } + } + + /* + actions, executed in version non-descending st_feature_version order + */ + for (i= i_0; i < i_1; i++) + { + /* Run time check of the st_feature_version items ordering */ + DBUG_ASSERT(!i || + version_product(features[i - 1].version_split) <= + version_product(features[i].version_split)); + + DBUG_ASSERT((downgrade ? master_version : current_version) < + version_product(features[i].version_split) && + (downgrade ? current_version : master_version > + version_product(features[i].version_split))); + + /* + An action is a pair of down- and up- grade components. + Add your case into the switch, order is irrelevant. + */ + switch (features[i].item) + { + case st_feature_version::WL6292_TIMESTAMP_EXPLICIT_DEFAULT: + if (downgrade) + { + thd->variables.explicit_defaults_for_timestamp= false; + } + else // upgrade + { + thd->variables.explicit_defaults_for_timestamp= + global_system_variables.explicit_defaults_for_timestamp; + } + break; + case st_feature_version::_END_OF_LIST: + break; + } + } +} === modified file 'sql/rpl_rli.h' --- a/sql/rpl_rli.h 2012-05-30 10:03:45 +0000 +++ b/sql/rpl_rli.h 2012-06-11 06:49:09 +0000 @@ -886,11 +886,8 @@ public: Delete the existing event and set a new one. This class is responsible for freeing the event, the caller should not do that. */ - void set_rli_description_event(Format_description_log_event *fdle) - { - delete rli_description_event; - rli_description_event= fdle; - } + virtual void set_rli_description_event(Format_description_log_event *fdle); + /** Return the current Format_description_log_event. */ @@ -899,9 +896,17 @@ public: return rli_description_event; } -private: + /** + adatation for the slave applier to specific master versions. + */ + void adapt_to_master_version(Format_description_log_event *fdle); + uchar slave_version_split[3]; // bytes of the slave server version + +protected: Format_description_log_event *rli_description_event; +private: + /** Delay slave SQL thread by this amount, compared to master (in seconds). This is set with CHANGE MASTER TO MASTER_DELAY=X. === modified file 'sql/rpl_rli_pdb.cc' --- a/sql/rpl_rli_pdb.cc 2012-05-07 08:53:28 +0000 +++ b/sql/rpl_rli_pdb.cc 2012-06-11 06:49:09 +0000 @@ -96,6 +96,7 @@ Slave_worker::~Slave_worker() delete_dynamic(&curr_group_exec_parts); mysql_mutex_destroy(&jobs_lock); mysql_cond_destroy(&jobs_cond); + set_rli_description_event(NULL); } /** === modified file 'sql/rpl_rli_pdb.h' --- a/sql/rpl_rli_pdb.h 2012-05-07 08:53:28 +0000 +++ b/sql/rpl_rli_pdb.h 2012-06-11 06:49:09 +0000 @@ -352,6 +352,18 @@ public: void slave_worker_ends_group(Log_event*, int); bool commit_positions(Log_event *evt, Slave_job_group *ptr_g, bool force); bool reset_recovery_info(); + /** + Different from the parent method in that this does not delete + rli_description_event. + The method runs by Coordinator when Worker are synched or being + destroyed. + */ + void set_rli_description_event(Format_description_log_event *fdle) + { + rli_description_event= fdle; + if (fdle && fdle->server_id != (uint32) ::server_id) + adapt_to_master_version(fdle); + } protected: === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2012-06-11 02:27:08 +0000 +++ b/sql/sql_parse.cc 2012-06-11 06:49:09 +0000 @@ -5819,48 +5819,6 @@ void THD::reset_for_next_command() thd->commit_error= 0; thd->durability_property= HA_REGULAR_DURABILITY; -#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - // If this is a replication SQL or WORKER thread - if (thd->slave_thread && - (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL || - thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER)) - { - Format_description_log_event *evt; - Relay_log_info *rli= thd->rli_slave; - - // Get server startup value for explicit_defaults_for_timestamp. - evt= rli->get_rli_description_event(); - thd->variables.explicit_defaults_for_timestamp= - global_system_variables.explicit_defaults_for_timestamp; - - /** - If format descriptor is not initialized, we can ignore handling - explicit_defaults_for_timestamp safely. This also means that no - reply log file is read yet. In such cases, this function is invoked - again after SQL thread has started reading relay log file. - - More specifically, - This ussually happens during startup of SQL thread handle_slave_sql(). - handle_slave_sql() invokes slave_start_workers() which hits here without - initializing description_event_for_exec. - Later handle_slave_sql() invokes rli->init_relay_log_pos() which - initializes description_event_for_exec. - */ - if (evt) - { - /* - Check if the master version in less than the current master version. - Then, the TIMESTAMP columns should assume default clause. - This is achieved by setting session variable - thd->variables->explicit_defaults_for_timestamp to false. - */ - if (thd->variables.explicit_defaults_for_timestamp && - evt->is_version_before_checksum()) - thd->variables.explicit_defaults_for_timestamp= false; - } - } -#endif - DBUG_PRINT("debug", ("is_current_stmt_binlog_format_row(): %d", thd->is_current_stmt_binlog_format_row())); No bundle (reason: useless for push emails).