From: Andrei Elkin Date: December 7 2010 5:35pm Subject: bzr commit into mysql-next-mr-wl5569 branch (andrei.elkin:3231) WL#5569 List-Archive: http://lists.mysql.com/commits/126249 Message-Id: <201012071735.oB7HZVkH027676@mysql1000.dsl.inet.fi> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0622978935==" --===============0622978935== 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 3231 Andrei Elkin 2010-12-07 wl#5569 MTS Testing related fixes incl master_pos_wait() support and thereafter replacing sleeps with the functioning sync_slave_with_master; Fixing the limitted Q-log-event parallelization. After the fixing mixture of rows- and Q- transactions can run concurrently. Q-transaction will be treated sequentially by default. @ mysql-test/suite/rpl/r/rpl_parallel.result results updated. @ mysql-test/suite/rpl/r/rpl_sequential.result results updated. @ mysql-test/suite/rpl/t/disabled.def a nuisance test gets disabled. @ mysql-test/suite/rpl/t/rpl_parallel_conf_limits.test sleeps go away. @ mysql-test/suite/rpl/t/rpl_parallel_conflicts.test sleeps go away. @ mysql-test/suite/rpl/t/rpl_parallel_start_stop.test sleeps go away. @ sql/log_event.cc Fullfiling long perding time todo:s wrt update_pos and delete ev, update_pos() is redundant being superseded by a special commit of the Worker; Addressing {B, Q, T} not-parallel case. The issue was due to unability to support Q-log-event as quickly as Rows- parallelization. @ sql/rpl_rli_pdb.cc circular_buffer_queue::de_tail() a very specific method is motivated by the limitted support for Q-log-ev parallelization. It may happen to be unnessary once Q has become parallel. @ sql/rpl_slave.cc Implementing CP in successful read branch. modified: mysql-test/extra/rpl_tests/rpl_parallel_load.test mysql-test/suite/rpl/r/rpl_parallel.result mysql-test/suite/rpl/r/rpl_parallel_conf_limits.result mysql-test/suite/rpl/r/rpl_sequential.result mysql-test/suite/rpl/t/disabled.def mysql-test/suite/rpl/t/rpl_parallel_conf_limits.test mysql-test/suite/rpl/t/rpl_parallel_conflicts.test mysql-test/suite/rpl/t/rpl_parallel_start_stop.test sql/log_event.cc sql/log_event.h sql/rpl_rli_pdb.cc sql/rpl_rli_pdb.h sql/rpl_slave.cc === modified file 'mysql-test/extra/rpl_tests/rpl_parallel_load.test' --- a/mysql-test/extra/rpl_tests/rpl_parallel_load.test 2010-12-04 17:14:50 +0000 +++ b/mysql-test/extra/rpl_tests/rpl_parallel_load.test 2010-12-07 17:35:16 +0000 @@ -87,17 +87,8 @@ while($i) --enable_query_log -#connection slave; - -# Exec log position is not accurate in the prototype ---sleep 2 ---disable_query_log ---disable_result_log -###select sleep(300); ---enable_result_log ---enable_query_log - sync_slave_with_master; +#connection slave; --disable_query_log --disable_result_log @@ -213,11 +204,6 @@ connection slave; --disable_query_log --disable_result_log -### --sleep 15 # todo: convert to wait for the last event has been applied - ---echo *** you can connect and change the exec mode as well now *** ---echo *** and select * from benchmark before to run consistency check *** - insert into test0.benchmark set state='slave is processing load'; # To force filling timestamp cols with the slave local clock values @@ -239,13 +225,6 @@ select ts from test0.benchmark where sta select time_to_sec(@m_1) - time_to_sec(@m_0) as 'delta_m', time_to_sec(@s_1) - time_to_sec(@s_0) as 'delta_s' into outfile 'delta.out'; -# debug: pre diff check-out ---disable_result_log ---disable_query_log -##select sleep(9999); ---enable_result_log ---enable_query_log - let $i = $databases + 1; while($i) { @@ -262,13 +241,6 @@ while($i) --enable_result_log --enable_query_log -# debug: pre diff check-out ---disable_result_log ---disable_query_log -##select sleep(9999); ---enable_result_log ---enable_query_log - connection master; @@ -288,12 +260,8 @@ while($i) --enable_result_log --enable_query_log -connection slave; - -# same as above - prototype Exec pos in not accurate ---sleep 5 - -#sync_slave_with_master; +sync_slave_with_master; +#connection slave; -# End of 4.1 tests +# End of the tests === modified file 'mysql-test/suite/rpl/r/rpl_parallel.result' --- a/mysql-test/suite/rpl/r/rpl_parallel.result 2010-12-02 17:46:46 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel.result 2010-12-07 17:35:16 +0000 @@ -12,8 +12,6 @@ call mtr.add_suppression('Slave: Error d include/stop_slave.inc start slave; stop slave sql_thread; -*** you can connect and change the exec mode as well now *** -*** and select * from benchmark before to run consistency check *** use test; select * from test0.benchmark into outfile 'benchmark.out'; select ts from test0.benchmark where state like 'master started load' into @m_0; === modified file 'mysql-test/suite/rpl/r/rpl_parallel_conf_limits.result' --- a/mysql-test/suite/rpl/r/rpl_parallel_conf_limits.result 2010-12-02 17:46:46 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel_conf_limits.result 2010-12-07 17:35:16 +0000 @@ -4,7 +4,9 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -create view coord_wait_list as SELECT id from Information_Schema.processlist where state like 'Waiting for Slave Worker%'; +create view coord_wait_list as +SELECT id from Information_Schema.processlist +where state like 'Waiting for Slave Worker%'; include/stop_slave.inc set @save.slave_parallel_workers= @@global.slave_parallel_workers; set @@global.slave_parallel_workers= 4; @@ -13,9 +15,6 @@ set @@global.mts_slave_worker_queue_len_ include/start_slave.inc create database d0; create table d0.t1 (a int auto_increment primary key) engine=innodb; -select sleep(2); -sleep(2) -0 begin; insert into d0.t1 set a=null; begin; === modified file 'mysql-test/suite/rpl/r/rpl_sequential.result' --- a/mysql-test/suite/rpl/r/rpl_sequential.result 2010-12-02 17:46:46 +0000 +++ b/mysql-test/suite/rpl/r/rpl_sequential.result 2010-12-07 17:35:16 +0000 @@ -12,8 +12,6 @@ call mtr.add_suppression('Slave: Error d include/stop_slave.inc start slave; stop slave sql_thread; -*** you can connect and change the exec mode as well now *** -*** and select * from benchmark before to run consistency check *** use test; select * from test0.benchmark into outfile 'benchmark.out'; select ts from test0.benchmark where state like 'master started load' into @m_0; === modified file 'mysql-test/suite/rpl/t/disabled.def' --- a/mysql-test/suite/rpl/t/disabled.def 2010-09-06 12:52:04 +0000 +++ b/mysql-test/suite/rpl/t/disabled.def 2010-12-07 17:35:16 +0000 @@ -12,3 +12,4 @@ rpl_row_create_table : Bug#51574 2010-02-27 andrei failed different way than earlier with bug#45576 rpl_spec_variables : BUG#47661 2009-10-27 jasonh rpl_spec_variables fails on PB2 hpux +rpl_row_ignorable_event : Bug#58784 7-12-2010 andrei rpl_row_ignorable_event fails on PB2 === modified file 'mysql-test/suite/rpl/t/rpl_parallel_conf_limits.test' --- a/mysql-test/suite/rpl/t/rpl_parallel_conf_limits.test 2010-12-02 17:46:46 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel_conf_limits.test 2010-12-07 17:35:16 +0000 @@ -2,8 +2,11 @@ # WL#5569 MTS # # The test verifies correctness of MTS execution when system meets -# various limits due to configuration options. +# various limits due to few configuration options: # +# @@global.mts_pending_jobs_size_max +# @@global.mts_slave_worker_queue_len_max +# @@global.mts_partition_hash_soft_max source include/master-slave.inc; # no support for Query-log-event in this test @@ -11,7 +14,9 @@ source include/have_binlog_format_row.in connection slave; -create view coord_wait_list as SELECT id from Information_Schema.processlist where state like 'Waiting for Slave Worker%'; +create view coord_wait_list as + SELECT id from Information_Schema.processlist + where state like 'Waiting for Slave Worker%'; # restart in Parallel source include/stop_slave.inc; @@ -30,9 +35,8 @@ create database d0; create table d0.t1 (a int auto_increment primary key) engine=innodb; -connection slave; +sync_slave_with_master; -select sleep(2); begin; insert into d0.t1 set a=null; # lock a row that master has inserted into @@ -87,14 +91,8 @@ source include/start_slave.inc; connection master; create table d0.t2 (a int auto_increment primary key, b text null) engine=innodb; -connection slave; +sync_slave_with_master; -# sync_slave_with_master ---disable_query_log ---disable_result_log -select sleep(2); ---enable_result_log ---enable_query_log begin; insert into d0.t2 set a= 1; @@ -180,17 +178,8 @@ while ($i) dec $i; } -# TODO: +sync_slave_with_master; -connection slave; - ---disable_query_log ---disable_result_log -select sleep(1); ---enable_result_log ---enable_query_log - -#sync_slave_with_master set @@global.mts_partition_hash_soft_max= @save.mts_partition_hash_soft_max; connection master; @@ -203,8 +192,8 @@ while ($i) } -connection slave; -#sync_slave_with_master +#connection slave; +sync_slave_with_master; # @@ -216,13 +205,10 @@ connection master; drop database d0; -# sync_slave_with_master -connection slave; +sync_slave_with_master; +#connection slave; drop view coord_wait_list; - ---sleep 2 - set @@global.slave_parallel_workers= @save.slave_parallel_workers; === modified file 'mysql-test/suite/rpl/t/rpl_parallel_conflicts.test' --- a/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test 2010-12-02 17:46:46 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test 2010-12-07 17:35:16 +0000 @@ -67,14 +67,9 @@ create table d3.t1 (a int auto_increment # # two conflicting jobs to follow -# sync_slave_with_master - -# TODO: remove once `sync_slave_with_master' got fixed - ---sleep 3 - +sync_slave_with_master; # To be really conflicting slave needs to block commit of the first. -connection slave; +#connection slave; begin; insert into d2.t1 values (1); @@ -210,10 +205,8 @@ drop database d1; drop database d2; drop database d3; ---sleep 4 - -connection slave; -#sync_slave_with_master; +sync_slave_with_master; +#connection slave; drop view coord_wait_list; set @@global.slave_parallel_workers= @save.slave_parallel_workers; === modified file 'mysql-test/suite/rpl/t/rpl_parallel_start_stop.test' --- a/mysql-test/suite/rpl/t/rpl_parallel_start_stop.test 2010-12-02 17:46:46 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel_start_stop.test 2010-12-07 17:35:16 +0000 @@ -53,12 +53,6 @@ source include/wait_until_rows_count.inc select id from coord_proc_list into @c_id; ---disable_query_log ---disable_result_log -#select sleep(300); ---enable_query_log ---enable_result_log - kill query @c_id; let $count= 0; @@ -80,20 +74,10 @@ CREATE TABLE t1 (a int primary key); insert into t1 values (1),(2); -# -# todo: remove when recovery recovers `sync_slave_with_master' -# - ---sleep 3 ---disable_result_log ---disable_query_log -#select sleep(600); ---enable_result_log ---enable_query_log +sync_slave_with_master; +#connection slave; -connection slave; -# sync_slave_with_master; let $count= 2; let $table= t1; source include/wait_until_rows_count.inc; @@ -112,12 +96,6 @@ let $count= 0; let $table= worker_proc_list; source include/wait_until_rows_count.inc; ---disable_result_log ---disable_query_log -#select sleep(600); ---enable_result_log ---enable_query_log - source include/wait_for_slave_sql_to_stop.inc; delete from t1; @@ -128,14 +106,8 @@ source include/start_slave.inc; connection master; drop table t1; -# -# todo: remove when recovery recovers `sync_slave_with_master' -# - ---sleep 3 - -connection slave; -#sync_slave_with_master; +sync_slave_with_master; +#connection slave; drop view worker_proc_list; drop view coord_proc_list; === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2010-12-05 20:04:17 +0000 +++ b/sql/log_event.cc 2010-12-07 17:35:16 +0000 @@ -2527,8 +2527,8 @@ int Log_event::apply_event(Relay_log_inf { if (parallel) { - // This case relates to Query parallel apply which breaks into - // DDL and {B, Q, T} group, where Q owns g-parallel property. + // This `only-sequential' case relates to Query parallel apply which + // breaks into DDL and {B, Q, T} group, where Q owns g-parallel property. // Apply possibly deferred B if (rli->curr_group_da.elements > 0) @@ -2539,9 +2539,16 @@ int Log_event::apply_event(Relay_log_inf DBUG_ASSERT(rli->curr_group_da.elements == 0); DBUG_ASSERT(rli->curr_group_seen_begin); - // TODO: rollback - // c_rli->gaq->assigned_group_index= rli->gaq->en_queue((void *) &g); + // While Query-log-event is not supported GAQ needs rollback + if (rli->curr_group_seen_begin) + { + Slave_job_group g; + ulong ind= rli->gaq->de_tail((uchar *) &g); + const_cast(rli)->mts_total_groups--; + DBUG_ASSERT(rli->last_assigned_worker == NULL); + DBUG_ASSERT(c_rli->gaq->assigned_group_index == ind); + } res= ev_begin->do_apply_event(rli); delete ev_begin; /* B appears to be serial, reset parallel status of group @@ -2716,6 +2723,13 @@ int slave_worker_exec_job(Slave_worker * w->slave_worker_ends_group(ev, error); /* last done sets post exec */ } + /* + commit_positions() fullfils group pos incr and flush + TODO: remove + if (!error) + ev->update_pos(w->w_rli); + */ + mysql_mutex_lock(&w->jobs_lock); de_queue(&w->jobs, job_item); @@ -2725,17 +2739,6 @@ int slave_worker_exec_job(Slave_worker * w->jobs.overfill= FALSE; mysql_cond_signal(&w->jobs_cond); } - - /* - preserving signatures of existing methods. - todo: convert update_pos(w->w_rli) -> update_pos(w) - to remove w_rli w/a - TODO: remove ? - */ - if (!error) - ev->update_pos(w->w_rli); - - mysql_mutex_unlock(&w->jobs_lock); /* statistics */ @@ -2786,9 +2789,8 @@ int slave_worker_exec_job(Slave_worker * err: - // TODO!!! ANDREI to RESTORE - // if (!ev) - // delete ev; // after ev->update_pos() event is garbage + if (!ev) + delete ev; // after ev->update_pos() event is garbage DBUG_RETURN(error); } === modified file 'sql/log_event.h' --- a/sql/log_event.h 2010-11-27 15:36:50 +0000 +++ b/sql/log_event.h 2010-12-07 17:35:16 +0000 @@ -1197,7 +1197,7 @@ public: } /** - MST: some events can be applied by Coordinator concurrently with Workers. + MST: some events have to be applied by Coordinator concurrently with Workers. @return TRUE if that's the case, FALSE otherwise. === modified file 'sql/rpl_rli_pdb.cc' --- a/sql/rpl_rli_pdb.cc 2010-12-04 17:14:50 +0000 +++ b/sql/rpl_rli_pdb.cc 2010-12-07 17:35:16 +0000 @@ -590,6 +590,33 @@ ulong circular_buffer_queue::de_queue(uc return ret; } +/** + removing an item from the tail side +*/ +ulong circular_buffer_queue::de_tail(uchar *val) +{ + ulong ret; + if (e == s) + { + DBUG_ASSERT(len == 0); + return (ulong) -1; + } + + a= (e + len - 1) % s; + get_dynamic(&Q, val, a); + len--; + + // post boundary cond + if (a == e) + e= s; + + DBUG_ASSERT(e == s || + (len == (a >= e)? (a - e) : + (s + a - e))); + + return a; + +} /** @return the used index at success or -1 when queue is full */ === modified file 'sql/rpl_rli_pdb.h' --- a/sql/rpl_rli_pdb.h 2010-12-04 17:14:50 +0000 +++ b/sql/rpl_rli_pdb.h 2010-12-07 17:35:16 +0000 @@ -67,10 +67,14 @@ public: location. @return the queue's array index that the de-queued item - locates at, or + located at, or an error encoded in beyond the index legacy range. */ ulong de_queue(uchar *); + /** + Similar to de_queue but extracting happens from the tail side. + */ + ulong de_tail(uchar *val); /** return the index where the arg item locates === modified file 'sql/rpl_slave.cc' --- a/sql/rpl_slave.cc 2010-12-05 20:04:17 +0000 +++ b/sql/rpl_slave.cc 2010-12-07 17:35:16 +0000 @@ -168,7 +168,7 @@ static int terminate_slave_thread(THD *t bool skip_lock); static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info); int slave_worker_exec_job(Slave_worker * w, Relay_log_info *rli); -bool mts_checkpoint_routine(Relay_log_info *rli); +static bool mts_checkpoint_routine(Relay_log_info *rli, bool locked); /* Find out which replications threads are running @@ -3617,7 +3617,7 @@ err: @return FALSE success, TRUE otherwise */ -bool mts_checkpoint_routine(Relay_log_info *rli) +bool mts_checkpoint_routine(Relay_log_info *rli, bool locked) { bool error= FALSE; ulong cnt; @@ -3638,7 +3638,8 @@ bool mts_checkpoint_routine(Relay_log_in }; sort_dynamic(&rli->least_occupied_workers, (qsort_cmp) ulong_cmp); - mysql_mutex_lock(&rli->data_lock); + if (!locked) + mysql_mutex_lock(&rli->data_lock); // Coordinator::commit_positions() { @@ -3647,6 +3648,9 @@ bool mts_checkpoint_routine(Relay_log_in // group_master_log_name is updated only by Coordinator and it can't change // within checkpoint interval because Coordinator flushes the updated value // at once. + // Note, unlike group_master_log_name, event_relay_log_pos is updated solely + // within Coordinator read loop context. Hence, it's possible at times + // event_rlp > group_rlp. rli->set_group_master_log_pos(rli->gaq->lwm.group_master_log_pos); rli->set_group_relay_log_pos(rli->gaq->lwm.group_relay_log_pos); @@ -3654,15 +3658,22 @@ bool mts_checkpoint_routine(Relay_log_in if (rli->gaq->lwm.group_relay_log_name[0] != 0) rli->set_group_relay_log_name(rli->gaq->lwm.group_relay_log_name); - error= rli->flush_info(TRUE); + //todo: uncomment notifies when UNTIL will be supported - // end of commit_positions + //rli->notify_group_master_log_name_update(); + //rli->notify_group_relay_log_name_update(); - mysql_mutex_unlock(&rli->data_lock); + // todo: optimize with if (wait_flag) broadcast + // waiter: set wait_flag; waits....; drops wait_flag; + mysql_cond_broadcast(&rli->data_cond); + if (!locked) + mysql_mutex_unlock(&rli->data_lock); + + error= rli->flush_info(TRUE); + // end of commit_positions end: - // ANDREI NOTIFICATIONS? DBUG_RETURN(error); } @@ -5235,6 +5246,23 @@ static Log_event* next_event(Relay_log_i ev->future_event_relay_log_pos= rli->get_future_event_relay_log_pos(); if (hot_log) mysql_mutex_unlock(log_lock); + /* + MTS checkpoint in the successful read branch + */ + if (rli->is_parallel_exec() && rli->lwm_period != 0.0) + { + int ret= 0; + struct timespec waittime; + ulong period= rli->lwm_period * 1000000000UL; + set_timespec_nsec(rli->curr_clock, 0); + ulong diff= diff_timespec(rli->curr_clock, rli->last_clock); + if (diff > period) + { + mts_checkpoint_routine(rli, TRUE); + set_timespec_nsec(rli->last_clock, 0); + } + } + DBUG_RETURN(ev); } DBUG_ASSERT(thd==rli->info_thd); @@ -5363,8 +5391,8 @@ static Log_event* next_event(Relay_log_i ulong diff= diff_timespec(rli->curr_clock, rli->last_clock); if (diff > period) { - mts_checkpoint_routine(rli); - set_timespec_nsec(rli->last_clock, 0); + mts_checkpoint_routine(rli, FALSE); + set_timespec_nsec(rli->last_clock, 0); } set_timespec_nsec(waittime, period); thd->enter_cond(log_cond, log_lock, --===============0622978935== 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: f576b868e445393672ea190f636e3a68e35b8ca2 # timestamp: 2010-12-07 19:35:31 +0200 # base_revision_id: andrei.elkin@stripped\ # lezfgpc9q24mezc3 # # Begin bundle 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 --===============0622978935==--