From: Andrei Elkin Date: June 10 2011 8:04am Subject: bzr commit into mysql-next-mr-wl5569 branch (andrei.elkin:3284) WL#5569 List-Archive: http://lists.mysql.com/commits/139035 Message-Id: <201106100804.p5A848ki021700@mysql1000.dsl.inet.fi> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1067214106==" --===============1067214106== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/andrei/MySQL/BZR/2a-23May/WL/mysql-next-mr-wl5569/ based on revid:andrei.elkin@stripped 3284 Andrei Elkin 2011-06-10 wl#5569 MTS This patch implements Seconds_behind_master (SBM) updating policy for MTS. The status parameter is updated per some number of processed group of events. The number can't be greater than @@global.slave_checkpoint_group and anyway SBM updating rate does not exceed @@global.slave_checkpoint_period. Notice that SBM is set to a new value after processing the terminal event (e.g Commit) of a group. Coordinator resets SBM when notices no more groups left neither to read from Relay-log nor to process by Workers. @ mysql-test/suite/rpl/t/rpl_parallel_seconds_behind_master.test SBM policy for MTS tests are added. @ mysql-test/suite/rpl/t/rpl_seconds_behind_master.test the currrent version of the test is MTS unfriendly. @ sql/log_event.cc Deploying association of the being assigned group with its terminal event's timestamp corresponding to end of the event execution. Making Rotate's update_pos method to modify SBM explicitly through reset_notified_checkpoint() rathen than mts_checkpoint_routine(). @ sql/rpl_rli.cc Making reset_notified_checkpoint() to install a new value of SBM. @ sql/rpl_rli.h Making reset_notified_checkpoint() to install a new value of SBM. @ sql/rpl_rli_pdb.h |Adding new member to transfer SBM of the group to Coordinator which it installs whenever it processes GAQ effectively. @ sql/rpl_slave.cc Coordinator installs SBM as timestamp of the last group discared from GAQ. Wait for new event Coordinator's read-loop is augmented to implement SBM resetting. added: mysql-test/suite/rpl/r/rpl_parallel_seconds_behind_master.result mysql-test/suite/rpl/t/rpl_parallel_seconds_behind_master.test modified: mysql-test/suite/rpl/t/rpl_seconds_behind_master.test sql/log_event.cc sql/rpl_rli.cc sql/rpl_rli.h sql/rpl_rli_pdb.h sql/rpl_slave.cc === added file 'mysql-test/suite/rpl/r/rpl_parallel_seconds_behind_master.result' --- a/mysql-test/suite/rpl/r/rpl_parallel_seconds_behind_master.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel_seconds_behind_master.result 2011-06-10 08:04:00 +0000 @@ -0,0 +1,35 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT'); +include/stop_slave.inc +set @save.mts_slave_parallel_workers= @@global.mts_slave_parallel_workers; +set @@global.mts_slave_parallel_workers= 4; +set @save.mts_checkpoint_period= @@global.mts_checkpoint_period; +set @@global.mts_checkpoint_period= 500; +set @save.slave_transaction_retries= @@global.slave_transaction_retries; +start slave io_thread; +include/wait_for_slave_io_to_start.inc +create table t1 (f1 int) engine=innodb; +create table t2 (f1 int) engine=innodb; +begin; +insert into t1 values (sleep(3) + 1); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +commit; +begin; +insert into t2 values (1); +commit; +include/start_slave.inc +include/sync_slave_io_with_master.inc +lock table t2 write; +First transaction is done, now get Seconds_Behind_Master after it... +include/wait_for_slave_param.inc [Seconds_Behind_Master] +Seconds_Behind_Master after first transaction is as expected. +unlock tables; +include/wait_for_slave_param.inc [Seconds_Behind_Master] +drop tables t1, t2; +set @@global.mts_checkpoint_period= @save.mts_checkpoint_period; +set @@global.mts_slave_parallel_workers= @save.mts_slave_parallel_workers; +set @@global.slave_transaction_retries= @save.slave_transaction_retries; +include/rpl_end.inc +end of the tests === added file 'mysql-test/suite/rpl/t/rpl_parallel_seconds_behind_master.test' --- a/mysql-test/suite/rpl/t/rpl_parallel_seconds_behind_master.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel_seconds_behind_master.test 2011-06-10 08:04:00 +0000 @@ -0,0 +1,141 @@ +# +# Testing of Seconds_Behind_Master (SBM) to behave as the following +# SBM changes discretely per some number of processed group of events, +# e.g transactions. +# The number is either @@global.slave_checkpoint_group or less if +# @@global.slave_checkpoint_period timer elapses first. +# The value updates *after* the last group commit is executed. +# Resetting to zero behaviour when Slave goes to read events is +# preserved. +# + +-- source include/master-slave.inc +-- source include/have_debug.inc + +# make the test only run once (STMT is actually needed because we rely +# on SHOW PROCESS LIST output in some of the tests) +-- source include/have_binlog_format_statement.inc + +# todo: sleep() is deterministic!!! +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT'); + +# restart slave in MTS mode +connection slave; +source include/stop_slave.inc; +set @save.mts_slave_parallel_workers= @@global.mts_slave_parallel_workers; +set @@global.mts_slave_parallel_workers= 4; +set @save.mts_checkpoint_period= @@global.mts_checkpoint_period; +set @@global.mts_checkpoint_period= 500; # 0.5 sec +# to avoid warnings +set @save.slave_transaction_retries= @@global.slave_transaction_retries; + +# +# Idea of demonstration. +# +# Two transactions on the same db are generated for MTS. The first has some +# natural delay, and the 2nd will be locked out of its data. +# While the first is being processed Coordinator empties the relay-log +# to enter waiting for more events. +# It does so being awakened @@global.slave_checkpoint_period-ically +# to check out if some groups of events have been done to update SBM (demo 1). +# +# Resetting of SBM is a possibility whenever Coordinator +# notices no more groups left neither to read nor to process (demo 2). +# + +start slave io_thread; +source include/wait_for_slave_io_to_start.inc; + +connection master; + +create table t1 (f1 int) engine=innodb; +create table t2 (f1 int) engine=innodb; +save_master_pos; + +# 1st transaction that will be used to compute SBM. +# It will hang $idle time at least in processing to get min estimate for SBM +let $idle= 3; + +begin; + eval insert into t1 values (sleep($idle) + 1); +commit; + +# 2nd transaction to block Coordinator from resetting SBM +begin; + insert into t2 values (1); +commit; + +connection slave; +source include/start_slave.inc; + +# +# all events are in relay-log +# +connection master; + +source include/sync_slave_io_with_master.inc; + +# tables are created on slave +connection slave; +sync_with_master; + +connection slave1; +lock table t2 write; # to block 2nd trans + +connection slave; + +let $count= 1; +let $table= t1; +source include/wait_until_rows_count.inc; + +--echo First transaction is done, now get Seconds_Behind_Master after it... + +# +# demo 1: +# So now 1st is over, and it SBM must have gain at least $idle seconds. +# +let $slave_param= Seconds_Behind_Master; +let $slave_param_comparison= >=; +let $slave_param_value= $idle; +source include/wait_for_slave_param.inc; + +# checking sanity of SBM value +let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); +let $lower_bound= $idle; +if (`SELECT $sbm < $idle`) +{ + -- echo *** Seconds behind master is $sbm less than minimum expected $idle *** + -- source include/show_rpl_debug_info.inc + -- die +} + +--echo Seconds_Behind_Master after first transaction is as expected. + +connection slave1; +unlock tables; + +# +# demo 2: Resetting of SBM upon all groups have been processed and +# nothing left in relay-log. +# +connection slave; +let $slave_param= Seconds_Behind_Master; +let $slave_param_comparison= =; +let $slave_param_value= 0; +source include/wait_for_slave_param.inc; + +## +# cleanup +## +connection master; +drop tables t1, t2; + +sync_slave_with_master; + +set @@global.mts_checkpoint_period= @save.mts_checkpoint_period; +set @@global.mts_slave_parallel_workers= @save.mts_slave_parallel_workers; +set @@global.slave_transaction_retries= @save.slave_transaction_retries; + +--source include/rpl_end.inc + +--echo end of the tests === modified file 'mysql-test/suite/rpl/t/rpl_seconds_behind_master.test' --- a/mysql-test/suite/rpl/t/rpl_seconds_behind_master.test 2010-12-19 17:22:30 +0000 +++ b/mysql-test/suite/rpl/t/rpl_seconds_behind_master.test 2011-06-10 08:04:00 +0000 @@ -5,6 +5,10 @@ # on SHOW PROCESS LIST output in some of the tests) -- source include/have_binlog_format_statement.inc +# this test logics requires adaption to MTS policies for SBM +# (see rpl_parallel_seconds_behind_master.test) +-- source include/not_mts_slave_parallel_workers.inc + SET @old_debug= @@global.debug; call mtr.add_suppression('Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT'); === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2011-06-08 20:18:08 +0000 +++ b/sql/log_event.cc 2011-06-10 08:04:00 +0000 @@ -2635,6 +2635,7 @@ Slave_worker *Log_event::get_slave_worke ret_worker->checkpoint_notified= TRUE; } ptr_g->checkpoint_seqno= rli->checkpoint_seqno; + ptr_g->ts= when + (time_t) exec_time; rli->checkpoint_seqno++; } @@ -6514,17 +6515,17 @@ int Rotate_log_event::do_update_pos(Rela ((!rli->is_parallel_exec() && !rli->is_in_group()) || rli->mts_group_status != Relay_log_info::MTS_IN_GROUP)) { + if (rli->is_parallel_exec()) + { + (void) mts_checkpoint_routine(rli, 0, FALSE, TRUE); // todo: error branch + } + mysql_mutex_lock(&rli->data_lock); DBUG_PRINT("info", ("old group_master_log_name: '%s' " "old group_master_log_pos: %lu", rli->get_group_master_log_name(), (ulong) rli->get_group_master_log_pos())); - if (rli->is_parallel_exec()) - { - (void) mts_checkpoint_routine(rli, 0, FALSE, TRUE); // todo: error branch - } - memcpy((void *)rli->get_group_master_log_name(), new_log_ident, ident_len + 1); rli->notify_group_master_log_name_update(); @@ -6537,7 +6538,7 @@ int Rotate_log_event::do_update_pos(Rela mysql_mutex_unlock(&rli->data_lock); rli->flush_info(TRUE); // todo: error branch if (rli->is_parallel_exec()) - rli->reset_notified_checkpoint(0); + rli->reset_notified_checkpoint(0, when + (time_t) exec_time); /* Reset thd->variables.option_bits and sql_mode etc, because this could be the signal of === modified file 'sql/rpl_rli.cc' --- a/sql/rpl_rli.cc 2011-06-08 20:18:08 +0000 +++ b/sql/rpl_rli.cc 2011-06-10 08:04:00 +0000 @@ -191,8 +191,14 @@ void Relay_log_info::reset_notified_rela Worker notices the new checkpoint value at the group commit to reset the current bitmap and starts using the clean bitmap indexed from zero of being reset checkpoint_seqno. + New seconds_behind_master timestamp is installed. + + @param shift number of bits to shift by Worker due to the current + checkpoint change. + @param new_ts new seconds_behind_master timestamp value unless zero. + Zero could be due to FD event. */ -void Relay_log_info::reset_notified_checkpoint(ulong shift) +void Relay_log_info::reset_notified_checkpoint(ulong shift, time_t new_ts= 0) { if (!is_parallel_exec()) return; @@ -207,6 +213,13 @@ void Relay_log_info::reset_notified_chec w->bitmap_shifted += shift; // to reset at passing the accumulate value into GAQ } checkpoint_seqno= 0; + + if (new_ts) + { + mysql_mutex_lock(&data_lock); + last_master_timestamp= new_ts; + mysql_mutex_unlock(&data_lock); + } } static inline int add_relay_log(Relay_log_info* rli,LOG_INFO* linfo) === modified file 'sql/rpl_rli.h' --- a/sql/rpl_rli.h 2011-06-08 20:18:08 +0000 +++ b/sql/rpl_rli.h 2011-06-10 08:04:00 +0000 @@ -537,7 +537,7 @@ public: Coordinator notifies Workers about this event. Coordinator and Workers maintain a bitmap of executed group that is reset with a new checkpoint. */ - void reset_notified_checkpoint(ulong); + void reset_notified_checkpoint(ulong, time_t); /** Helper function to do after statement completion. === modified file 'sql/rpl_rli_pdb.h' --- a/sql/rpl_rli_pdb.h 2011-06-08 20:18:08 +0000 +++ b/sql/rpl_rli_pdb.h 2011-06-10 08:04:00 +0000 @@ -144,7 +144,8 @@ typedef struct st_slave_job_group my_off_t checkpoint_relay_log_pos; // T-event lop_pos filled by W for CheckPoint char* checkpoint_relay_log_name; volatile uchar done; // Flag raised by W, read and reset by C - ulong shifted; // shift the last CP bitmap at receiving a new CP + ulong shifted; // shift the last CP bitmap at receiving a new CP + time_t ts; // Group's timestampt to update Seconds_behind_master } Slave_job_group; #define retrieve_job(from, to) \ === modified file 'sql/rpl_slave.cc' --- a/sql/rpl_slave.cc 2011-06-08 20:18:08 +0000 +++ b/sql/rpl_slave.cc 2011-06-10 08:04:00 +0000 @@ -3088,7 +3088,8 @@ static int exec_relay_log_event(THD* thd event) or ev->when is set to 0, or a FD from master, we don't update the last_master_timestamp. */ - if (!(ev->is_artificial_event() || ev->is_relay_log_event() || + if (!(rli->is_parallel_exec() || + ev->is_artificial_event() || ev->is_relay_log_event() || (ev->when == 0) || ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)) { rli->last_master_timestamp= ev->when + (time_t) ev->exec_time; @@ -4153,7 +4154,7 @@ bool mts_checkpoint_routine(Relay_log_in } // end of commit_positions */ - rli->reset_notified_checkpoint(cnt); + rli->reset_notified_checkpoint(cnt, rli->gaq->lwm.ts); end: set_timespec_nsec(rli->last_clock, 0); @@ -6005,7 +6006,8 @@ static Log_event* next_event(Relay_log_i /* shows zero while it is sleeping (and until the next event is about to be executed) */ - rli->last_master_timestamp= 0; + if (!rli->is_parallel_exec()) + rli->last_master_timestamp= 0; DBUG_ASSERT(rli->relay_log.get_open_count() == rli->cur_log_old_open_count); @@ -6089,6 +6091,8 @@ static Log_event* next_event(Relay_log_i mysql_mutex_unlock(log_lock); mts_checkpoint_routine(rli, period, FALSE, FALSE); // TODO: ALFRANIO ERROR mysql_mutex_lock(log_lock); + if (rli->gaq->empty()) + rli->last_master_timestamp= 0; set_timespec_nsec(waittime, period); thd->enter_cond(log_cond, log_lock, --===============1067214106== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/andrei.elkin@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: andrei.elkin@stripped # target_branch: file:///home/andrei/MySQL/BZR/2a-23May/WL/mysql-next-\ # mr-wl5569/ # testament_sha1: 141f031b7abef59e2ddc2f062fcf4a3eeea04592 # timestamp: 2011-06-10 11:04:07 +0300 # source_branch: file:///home/andrei/MySQL/BZR/2a-23May/mysql-trunk/ # base_revision_id: andrei.elkin@stripped\ # h9279ue551ngalo9 # # Begin bundle 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 4II7gA== --===============1067214106==--