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).
| Thread |
|---|
| • bzr push into mysql-trunk-wl6292 branch (gopal.shankar:3924 to 3925) WL#6292 | Gopal Shankar | 11 Jun |