From: Andrei Elkin Date: December 16 2010 10:01pm Subject: bzr push into mysql-next-mr-wl5569 branch (andrei.elkin:3248) WL#5569 List-Archive: http://lists.mysql.com/commits/127117 Message-Id: <201012162201.oBGM1mIT011798@mysql1000.dsl.inet.fi> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1876489127==" --===============1876489127== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 3248 Andrei Elkin 2010-12-17 [merge] merge from wl#5569 repo to local branch rpl_sequential opt files are added to avoid mtr give up to process a bulk of unsafe warnings. added: mysql-test/suite/rpl/t/rpl_sequential-master.opt mysql-test/suite/rpl/t/rpl_sequential-slave.opt modified: mysql-test/suite/funcs_1/r/is_columns_mysql.result mysql-test/suite/rpl/r/rpl_mixed_crash_safe.result mysql-test/suite/rpl/r/rpl_row_crash_safe.result mysql-test/suite/rpl/r/rpl_stm_crash_safe.result scripts/mysql_system_tables.sql sql/rpl_info_dummy.cc sql/rpl_info_dummy.h sql/rpl_info_factory.cc sql/rpl_info_file.cc sql/rpl_info_file.h sql/rpl_info_handler.h sql/rpl_info_table.cc sql/rpl_info_table.h sql/rpl_info_table_access.cc sql/rpl_mi.cc sql/rpl_rli.cc sql/rpl_rli.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-14 08:57:16 +0000 +++ b/mysql-test/extra/rpl_tests/rpl_parallel_load.test 2010-12-16 21:41:45 +0000 @@ -6,7 +6,7 @@ # load volume parameter # -let $iter = 2000; +let $iter = 1000; let $databases = 4; connection slave; @@ -71,10 +71,26 @@ while($i) eval create database test$i1; eval use test$i1; - create table tm_nk (a int, b int) engine=myisam; - create table tm_wk (a int auto_increment primary key, b int) engine=myisam; - create table ti_nk (a int, b int) engine=innodb; - create table ti_wk (a int auto_increment primary key, b int) engine=innodb; + create table tm_nk (a int, b int, c text) engine=myisam; + create table tm_wk (a int auto_increment primary key, b int, c text) engine=myisam; + create table ti_nk (a int, b int, c text) engine=innodb; + create table ti_wk (a int auto_increment primary key, b int, c text) engine=innodb; + + if (`select @@global.binlog_format like 'statement'`) + { + create view v_tm_nk as select a,b from tm_nk; + create view v_tm_wk as select a,b from tm_wk; + create view v_ti_nk as select a,b from ti_nk; + create view v_ti_wk as select a,b from ti_wk; + } + + if (`select @@global.binlog_format not like 'statement'`) + { + create view v_tm_nk as select a,b,c from tm_nk; + create view v_tm_wk as select a,b,c from tm_wk; + create view v_ti_nk as select a,b,c from ti_nk; + create view v_ti_wk as select a,b,c from ti_wk; + } # this table is special - just for timing. It's more special on test0 db # where it contains master timing of the load as well. @@ -158,11 +174,19 @@ while ($iter) eval use test$i1; ##call test.one_session(1); - eval insert into tm_nk values($iter, $i1); - eval insert into tm_wk values(null, $i1); - eval insert into ti_nk values($iter, $i1); - eval insert into ti_wk values(null, $i1); - + eval insert into tm_nk values($iter, $i1, uuid()); + eval insert into tm_wk values(null, $i1, uuid()); + eval insert into ti_nk values($iter, $i1, uuid()); + eval insert into ti_wk values(null, $i1, uuid()); + + begin; + eval insert into tm_nk values($iter, $i1, repeat('a', round(rand()*10))); + eval insert into tm_wk values(null, $i1, uuid()); + commit; + begin; + eval insert into ti_nk values($iter, $i1, uuid()); + eval insert into ti_wk values(null, $i1, repeat('a', round(rand()*10))); + commit; dec $i; } @@ -226,21 +250,34 @@ 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'; +--enable_result_log +--enable_query_log + let $i = $databases + 1; while($i) { let $i1 = $i; dec $i1; - let $diff_table_1=master:test$i1.tm_nk; - let $diff_table_2=slave:test$i1.tm_nk; + let $diff_table_1=master:test$i1.v_tm_nk; + let $diff_table_2=slave:test$i1.v_tm_nk; + source include/diff_tables.inc; + + let $diff_table_1=master:test$i1.v_ti_nk; + let $diff_table_2=slave:test$i1.v_ti_nk; + source include/diff_tables.inc; + + let $diff_table_1=master:test$i1.v_tm_wk; + let $diff_table_2=slave:test$i1.v_tm_wk; + source include/diff_tables.inc; + + let $diff_table_1=master:test$i1.v_ti_wk; + let $diff_table_2=slave:test$i1.v_ti_wk; source include/diff_tables.inc; dec $i; } ---enable_result_log ---enable_query_log connection master; === modified file 'mysql-test/r/mysqld--help-win.result' --- a/mysql-test/r/mysqld--help-win.result 2010-12-14 12:51:30 +0000 +++ b/mysql-test/r/mysqld--help-win.result 2010-12-16 21:41:45 +0000 @@ -345,6 +345,16 @@ The following options may be given as th disk after every #th milli-seconds. The zero value disables the checkpoint routine (makes sense for debugging). + --mts-coordinator-basic-nap=# + Time in msec to sleep by MTS Coordinator to avoid the + Worker queues room overrun + --mts-exp-slave-local-timestamp + If enabled slave itself computes the event appying time + value to implicitly affected timestamp columms. Otherwise + (default) it installs prescribed by the master value + --mts-exp-slave-run-query-in-parallel + The default not an actual database name is used as + partition info for parallel execution of Query_log_event --mts-partition-hash-soft-max=# Number of records in the mts partition hash below which entries with zero usage are tolerated @@ -352,6 +362,8 @@ The following options may be given as th Max size of Slave Worker queues holding yet not applied events.The least possible value must be not less than the master size max_allowed_packet. + --mts-slave-parallel-workers=# + Number of worker threads for executing events in parallel --mts-slave-worker-queue-len-max=# Max length of one MTS Worker queue. Presence in the queue indicates a replication event was read out of Relay log @@ -360,6 +372,9 @@ The following options may be given as th Whichever limit is reached Coordinator threadsuspends further jobs assigning until conditions have been improved. + --mts-worker-underrun-level=# + percent of Worker queue size at which Worker is + considered to become hungry --multi-range-count=# Number of key ranges to request at once --myisam-block-size=# @@ -415,12 +430,6 @@ The following options may be given as th value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors - --opt-mts-coordinator-basic-nap=# - Time in msec to sleep by MTS Coordinator to avoid the - Worker queues room overrun - --opt-mts-worker-underrun-level=# - percent of Worker queue size at which Worker is - considered to become hungry --optimizer-join-cache-level=# Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers @@ -664,18 +673,9 @@ The following options may be given as th --slave-load-tmpdir=name The location where the slave should put its temporary files when replicating a LOAD DATA INFILE command - --slave-local-timestamp - if enabled slave computes the event appying time value to - implicitly affected timestamp columms. Otherwise - (default) installs prescribed by the master value --slave-net-timeout=# Number of seconds to wait for more data from a master/slave connection before aborting the read - --slave-parallel-workers=# - Number of worker threads for executing events in parallel - --slave-run-query-in-parallel - The default not an actual database name is used as - partition info for parallel execution of Query_log_event --slave-skip-errors=name Tells the slave thread to continue replication when a query event returns an error from the provided list @@ -899,9 +899,14 @@ max-write-lock-count 1844674407370955161 memlock FALSE min-examined-row-limit 0 mts-checkpoint-period 300 +mts-coordinator-basic-nap 5 +mts-exp-slave-local-timestamp FALSE +mts-exp-slave-run-query-in-parallel FALSE mts-partition-hash-soft-max 16 mts-pending-jobs-size-max 16777216 +mts-slave-parallel-workers 0 mts-slave-worker-queue-len-max 40000 +mts-worker-underrun-level 0 multi-range-count 256 myisam-block-size 1024 myisam-data-pointer-size 6 @@ -922,8 +927,6 @@ old FALSE old-alter-table FALSE old-passwords FALSE old-style-user-limits FALSE -opt-mts-coordinator-basic-nap 5 -opt-mts-worker-underrun-level 0 optimizer-join-cache-level 4 optimizer-prune-level 1 optimizer-search-depth 62 @@ -989,10 +992,7 @@ skip-show-database FALSE skip-slave-start FALSE slave-compressed-protocol FALSE slave-exec-mode STRICT -slave-local-timestamp FALSE slave-net-timeout 3600 -slave-parallel-workers 0 -slave-run-query-in-parallel FALSE slave-skip-errors (No default value) slave-sql-verify-checksum TRUE slave-transaction-retries 10 === modified file 'mysql-test/suite/rpl/r/rpl_parallel.result' --- a/mysql-test/suite/rpl/r/rpl_parallel.result 2010-12-14 08:57:16 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel.result 2010-12-16 21:41:45 +0000 @@ -24,9 +24,21 @@ select ts from test0.benchmark where sta select ts from test0.benchmark where state like 'slave ends load' into @s_1; 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'; -Comparing tables master:test3.tm_nk and slave:test3.tm_nk -Comparing tables master:test2.tm_nk and slave:test2.tm_nk -Comparing tables master:test1.tm_nk and slave:test1.tm_nk -Comparing tables master:test0.tm_nk and slave:test0.tm_nk +Comparing tables master:test3.v_tm_nk and slave:test3.v_tm_nk +Comparing tables master:test3.v_ti_nk and slave:test3.v_ti_nk +Comparing tables master:test3.v_tm_wk and slave:test3.v_tm_wk +Comparing tables master:test3.v_ti_wk and slave:test3.v_ti_wk +Comparing tables master:test2.v_tm_nk and slave:test2.v_tm_nk +Comparing tables master:test2.v_ti_nk and slave:test2.v_ti_nk +Comparing tables master:test2.v_tm_wk and slave:test2.v_tm_wk +Comparing tables master:test2.v_ti_wk and slave:test2.v_ti_wk +Comparing tables master:test1.v_tm_nk and slave:test1.v_tm_nk +Comparing tables master:test1.v_ti_nk and slave:test1.v_ti_nk +Comparing tables master:test1.v_tm_wk and slave:test1.v_tm_wk +Comparing tables master:test1.v_ti_wk and slave:test1.v_ti_wk +Comparing tables master:test0.v_tm_nk and slave:test0.v_tm_nk +Comparing tables master:test0.v_ti_nk and slave:test0.v_ti_nk +Comparing tables master:test0.v_tm_wk and slave:test0.v_tm_wk +Comparing tables master:test0.v_ti_wk and slave:test0.v_ti_wk set @@global.mts_exp_slave_local_timestamp= @save.mts_exp_slave_local_timestamp; set @@global.mts_slave_parallel_workers= @save.mts_slave_parallel_workers; === added file 'mysql-test/suite/rpl/r/rpl_parallel_fallback.result' --- a/mysql-test/suite/rpl/r/rpl_parallel_fallback.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel_fallback.result 2010-12-16 21:41:45 +0000 @@ -0,0 +1,24 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +include/stop_slave.inc +set @save.mts_slave_parallel_workers= @@global.mts_slave_parallel_workers; +set @@global.mts_slave_parallel_workers= 4; +Warnings: +Note 1724 Temporary failed transaction retry is not supported in Parallel Slave. Such failure will force the slave to stop. +include/start_slave.inc +set @@session.binlog_format= row; +create database d0; +create table d0.t1 (a int auto_increment primary key) engine=innodb; +set @@session.binlog_format= row; +create database d1; +create table d1.t1 (a int auto_increment primary key) engine=innodb; +set @@session.binlog_rows_query_log_events= 1; +set @@session.binlog_rows_query_log_events= 0; +Comparing tables master:d0.t1 and slave:d0.t1 +drop database d0; +drop database d1; +set @@global.mts_slave_parallel_workers= @save.mts_slave_parallel_workers; === modified file 'mysql-test/suite/rpl/r/rpl_sequential.result' --- a/mysql-test/suite/rpl/r/rpl_sequential.result 2010-12-14 08:57:16 +0000 +++ b/mysql-test/suite/rpl/r/rpl_sequential.result 2010-12-16 21:41:45 +0000 @@ -20,8 +20,20 @@ select ts from test0.benchmark where sta select ts from test0.benchmark where state like 'slave ends load' into @s_1; 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'; -Comparing tables master:test3.tm_nk and slave:test3.tm_nk -Comparing tables master:test2.tm_nk and slave:test2.tm_nk -Comparing tables master:test1.tm_nk and slave:test1.tm_nk -Comparing tables master:test0.tm_nk and slave:test0.tm_nk +Comparing tables master:test3.v_tm_nk and slave:test3.v_tm_nk +Comparing tables master:test3.v_ti_nk and slave:test3.v_ti_nk +Comparing tables master:test3.v_tm_wk and slave:test3.v_tm_wk +Comparing tables master:test3.v_ti_wk and slave:test3.v_ti_wk +Comparing tables master:test2.v_tm_nk and slave:test2.v_tm_nk +Comparing tables master:test2.v_ti_nk and slave:test2.v_ti_nk +Comparing tables master:test2.v_tm_wk and slave:test2.v_tm_wk +Comparing tables master:test2.v_ti_wk and slave:test2.v_ti_wk +Comparing tables master:test1.v_tm_nk and slave:test1.v_tm_nk +Comparing tables master:test1.v_ti_nk and slave:test1.v_ti_nk +Comparing tables master:test1.v_tm_wk and slave:test1.v_tm_wk +Comparing tables master:test1.v_ti_wk and slave:test1.v_ti_wk +Comparing tables master:test0.v_tm_nk and slave:test0.v_tm_nk +Comparing tables master:test0.v_ti_nk and slave:test0.v_ti_nk +Comparing tables master:test0.v_tm_wk and slave:test0.v_tm_wk +Comparing tables master:test0.v_ti_wk and slave:test0.v_ti_wk set @@global.mts_exp_slave_local_timestamp= @save.mts_exp_slave_local_timestamp; === added file 'mysql-test/suite/rpl/t/rpl_parallel-master.opt' --- a/mysql-test/suite/rpl/t/rpl_parallel-master.opt 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel-master.opt 2010-12-16 21:41:45 +0000 @@ -0,0 +1 @@ +--log-warnings=0 === modified file 'mysql-test/suite/rpl/t/rpl_parallel-slave.opt' --- a/mysql-test/suite/rpl/t/rpl_parallel-slave.opt 2010-12-14 08:57:16 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel-slave.opt 2010-12-16 21:41:45 +0000 @@ -1 +1,2 @@ ---mts-slave-parallel-workers=4 +--mts-slave-parallel-workers=4 --log-warnings=0 + === modified file 'mysql-test/suite/rpl/t/rpl_parallel.test' --- a/mysql-test/suite/rpl/t/rpl_parallel.test 2010-12-14 08:57:16 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel.test 2010-12-16 21:41:45 +0000 @@ -34,7 +34,7 @@ # source include/master-slave.inc; -source include/have_binlog_format_row.inc; +# source include/have_binlog_format_row.inc; connection slave; set @save.mts_slave_parallel_workers= @@global.mts_slave_parallel_workers; === added file 'mysql-test/suite/rpl/t/rpl_parallel_fallback.test' --- a/mysql-test/suite/rpl/t/rpl_parallel_fallback.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel_fallback.test 2010-12-16 21:41:45 +0000 @@ -0,0 +1,93 @@ +# +# WL#5569 MTS +# +# The test lists cases of transparent fallback to the sequential execution and +# verifies it correctness. +# Notice, the Query-log-event fallback is largely tested by rpl_parallel. +# + +source include/master-slave.inc; +source include/have_binlog_format_mixed.inc; + +let $workers= 4; + +connection slave; + +# restart in Parallel +source include/stop_slave.inc; +set @save.mts_slave_parallel_workers= @@global.mts_slave_parallel_workers; +eval set @@global.mts_slave_parallel_workers= $workers; +source include/start_slave.inc; + +connection master; + +set @@session.binlog_format= row; +create database d0; +create table d0.t1 (a int auto_increment primary key) engine=innodb; + +connection master1; + +set @@session.binlog_format= row; +create database d1; +create table d1.t1 (a int auto_increment primary key) engine=innodb; + +# +# Rows_query_log_event case +# + +let $iter= 100; +let $i= $iter; + +connection master; +set @@session.binlog_rows_query_log_events= 1; + +connection master1; +set @@session.binlog_rows_query_log_events= 0; + +--disable_query_log +--disable_result_log + +while ($i) +{ + connection master; + begin; + insert into d0.t1 values(null); + insert into d1.t1 values(null); + commit; + + connection master1; + begin; + insert into d1.t1 values(null); + insert into d0.t1 values(null); + commit; + + dec $i; +} + +--enable_result_log +--enable_query_log + +sync_slave_with_master; + +# verification + +let $diff_table_1=master:d0.t1; +let $diff_table_2= slave:d0.t1; +source include/diff_tables.inc; + + +# +# cleanup +# + +connection master; + +drop database d0; +drop database d1; + + +sync_slave_with_master; +#connection slave; +set @@global.mts_slave_parallel_workers= @save.mts_slave_parallel_workers; + + === added file 'mysql-test/suite/rpl/t/rpl_sequential-master.opt' --- a/mysql-test/suite/rpl/t/rpl_sequential-master.opt 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/t/rpl_sequential-master.opt 2010-12-16 22:00:47 +0000 @@ -0,0 +1 @@ +--log-warnings=0 === added file 'mysql-test/suite/rpl/t/rpl_sequential-slave.opt' --- a/mysql-test/suite/rpl/t/rpl_sequential-slave.opt 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/t/rpl_sequential-slave.opt 2010-12-16 22:00:47 +0000 @@ -0,0 +1,2 @@ +--log-warnings=0 + === modified file 'mysql-test/suite/sys_vars/r/all_vars.result' --- a/mysql-test/suite/sys_vars/r/all_vars.result 2010-12-13 21:16:31 +0000 +++ b/mysql-test/suite/sys_vars/r/all_vars.result 2010-12-16 21:41:45 +0000 @@ -11,16 +11,17 @@ There should be *no* long test name list select variable_name as `There should be *no* variables listed below:` from t2 left join t1 on variable_name=test_name where test_name is null; There should be *no* variables listed below: -OPT_MTS_COORDINATOR_BASIC_NAP INNODB_STATS_TRANSIENT_SAMPLE_PAGES MTS_PARTITION_HASH_SOFT_MAX -OPT_MTS_WORKER_UNDERRUN_LEVEL -SLAVE_RUN_QUERY_IN_PARALLEL +MTS_EXP_SLAVE_LOCAL_TIMESTAMP +MTS_EXP_SLAVE_RUN_QUERY_IN_PARALLEL INNODB_STATS_PERSISTENT_SAMPLE_PAGES RELAY_LOG_BASENAME LOG_BIN_BASENAME INNODB_ANALYZE_IS_PERSISTENT INNODB_RESET_MONITOR_COUNTER +MTS_SLAVE_PARALLEL_WORKERS +MTS_WORKER_UNDERRUN_LEVEL INNODB_RESET_ALL_MONITOR_COUNTER LOG_BIN_INDEX INNODB_DISABLE_MONITOR_COUNTER @@ -28,18 +29,18 @@ INNODB_ENABLE_MONITOR_COUNTER MTS_SLAVE_WORKER_QUEUE_LEN_MAX INNODB_FILE_FORMAT_MAX MTS_PENDING_JOBS_SIZE_MAX -SLAVE_PARALLEL_WORKERS -SLAVE_LOCAL_TIMESTAMP -OPT_MTS_COORDINATOR_BASIC_NAP +MTS_COORDINATOR_BASIC_NAP INNODB_STATS_TRANSIENT_SAMPLE_PAGES MTS_PARTITION_HASH_SOFT_MAX -OPT_MTS_WORKER_UNDERRUN_LEVEL -SLAVE_RUN_QUERY_IN_PARALLEL +MTS_EXP_SLAVE_LOCAL_TIMESTAMP +MTS_EXP_SLAVE_RUN_QUERY_IN_PARALLEL INNODB_STATS_PERSISTENT_SAMPLE_PAGES RELAY_LOG_BASENAME LOG_BIN_BASENAME INNODB_ANALYZE_IS_PERSISTENT INNODB_RESET_MONITOR_COUNTER +MTS_SLAVE_PARALLEL_WORKERS +MTS_WORKER_UNDERRUN_LEVEL INNODB_RESET_ALL_MONITOR_COUNTER LOG_BIN_INDEX INNODB_DISABLE_MONITOR_COUNTER @@ -47,7 +48,6 @@ INNODB_ENABLE_MONITOR_COUNTER MTS_SLAVE_WORKER_QUEUE_LEN_MAX INNODB_FILE_FORMAT_MAX MTS_PENDING_JOBS_SIZE_MAX -SLAVE_PARALLEL_WORKERS -SLAVE_LOCAL_TIMESTAMP +MTS_COORDINATOR_BASIC_NAP drop table t1; drop table t2; === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2010-12-14 08:57:16 +0000 +++ b/sql/log_event.cc 2010-12-16 21:41:45 +0000 @@ -176,7 +176,8 @@ void handle_rows_query_log_event(Log_eve ev_type == UPDATE_ROWS_EVENT) && rli->rows_query_ev != NULL && ((Rows_log_event*) ev)->get_flags(Rows_log_event::STMT_END_F)) { - delete rli->rows_query_ev; + if (rli->rows_query_ev) + delete rli->rows_query_ev; rli->rows_query_ev= NULL; rli->info_thd->set_query(NULL, 0); } @@ -2365,8 +2366,8 @@ bool Log_event::contains_partition_info( { return get_type_code() == TABLE_MAP_EVENT || - // todo: the 4 types below are limitly parallel-supported (the default - // session db not the actual db) + // todo: Query event is limitly supported + // which ev->get_db() yields the session db not the actual db get_type_code() == QUERY_EVENT; } @@ -2449,12 +2450,14 @@ Slave_worker *Log_event::get_slave_worke // mark the current grup as started with B-event const_cast(rli)->curr_group_seen_begin= TRUE; - return NULL; } else { DBUG_ASSERT(!rli->curr_group_seen_begin); } + // serves as a mark for Coord to delete events otherwise + const_cast(rli)->curr_group_is_parallel= TRUE; + return NULL; } //else // g @@ -2471,7 +2474,6 @@ Slave_worker *Log_event::get_slave_worke set_dynamic(&rli->gaq->Q, (uchar*) &g, rli->gaq->assigned_group_index); DBUG_ASSERT(g.group_relay_log_name == NULL); - } } else // r @@ -2502,6 +2504,7 @@ Slave_worker *Log_event::get_slave_worke (Slave_job_group *) dynamic_array_ptr(&rli->gaq->Q, rli->gaq->assigned_group_index); + DBUG_ASSERT(rli->curr_group_is_parallel); // TODO: throw an error when relay-log reading starts from inside of a group!! @@ -2560,7 +2563,6 @@ Slave_worker *Log_event::get_slave_worke // reset the B-group marker const_cast(rli)->curr_group_seen_begin= FALSE; - const_cast(rli)->curr_group_is_parallel= TRUE; // mark for Coord's T-event delete } return worker; @@ -2748,16 +2750,22 @@ int Log_event::apply_event(Relay_log_inf Slave_job_item item= {NULL}, *job_item= &item; Relay_log_info *c_rli= const_cast(rli); // constless alias bool parallel; + bool seq_event; + bool term_event; if (!(parallel= rli->is_parallel_exec()) || - only_sequential_exec(rli->run_query_in_parallel, rli->curr_group_seen_begin)) + ((seq_event= + only_sequential_exec(rli->run_query_in_parallel, + rli->curr_group_seen_begin /* todo: obs 2nd arg */)) + // rli->curr_group_seen_begin && ends_group() => rli->last_assigned_worker + && !rli->curr_group_seen_begin)) { if (parallel) { - // This `only-sequential' 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 a DDL Query case - // Apply possibly deferred B + DBUG_ASSERT(rli->curr_group_da.elements == 0); +#if 0 if (rli->curr_group_da.elements > 0) { int res; @@ -2778,27 +2786,45 @@ int Log_event::apply_event(Relay_log_inf } res= ev_begin->do_apply_event(rli); delete ev_begin; - /* B appears to be serial, reset parallel status of group - because the following T won't do that */ - c_rli->curr_group_seen_begin= FALSE; - + c_rli->curr_group_is_parallel= FALSE; // Coord will destruct events if (res) DBUG_RETURN(res); } - +#endif DBUG_ASSERT(!rli->curr_group_seen_begin); - c_rli->curr_group_is_parallel= FALSE; // Coord will destruct all the rest of events + + c_rli->curr_group_is_parallel= FALSE; // Coord will destruct events if (!parallel_exec_by_coordinator(::server_id)) (void) wait_for_workers_to_finish(rli); } DBUG_RETURN(do_apply_event(rli)); } + + DBUG_ASSERT(!(rli->curr_group_seen_begin && ends_group()) || + rli->last_assigned_worker); - if (get_type_code() == ROWS_QUERY_LOG_EVENT) - { - rli->report(ERROR_LEVEL, 0, - "No parallel support for ROWS_QUERY_LOG_EVENT"); - DBUG_RETURN(1); + /* + Work-around:s for B, T,..., Q case and ROWS_QUERY_LOG_EVENT + A worker has been assigned but it needs sequential environment. + + Todo: support Query parallelization. + Todo: disassociate Rows_* events from the central rli. + */ + if (seq_event) + { // rli->last_assigned_worker != NULL if BTQ but not BQT + DBUG_ASSERT(rli->curr_group_seen_begin || ends_group()); + if (!c_rli->curr_group_isolated) + (void) wait_for_workers_to_finish(rli, rli->last_assigned_worker); + c_rli->curr_group_isolated= TRUE; + + if (get_type_code() == ROWS_QUERY_LOG_EVENT) + { + while (c_rli->rows_query_ev != NULL) + { + my_sleep(10); + } + c_rli->rows_query_ev= (Rows_query_log_event*) this; + } } if ((!(w= get_slave_worker_id(rli)) || @@ -2832,7 +2858,17 @@ int Log_event::apply_event(Relay_log_inf c_rli->curr_group_da.elements= 0; } + if (c_rli->curr_group_isolated) + term_event= ends_group(); + append_item_to_jobs(job_item, w, c_rli); + + if (c_rli->curr_group_isolated && term_event) + { + (void) wait_for_workers_to_finish(rli); + c_rli->curr_group_isolated= FALSE; + } + DBUG_RETURN(FALSE); } @@ -3016,7 +3052,8 @@ int slave_worker_exec_job(Slave_worker * err: - if (!ev) + // todo: fix w/a for Rows_query_log_event + if (ev && ev->get_type_code() != ROWS_QUERY_LOG_EVENT) delete ev; // after ev->update_pos() event is garbage DBUG_RETURN(error); @@ -11196,7 +11233,7 @@ Rows_query_log_event::write_data_body(IO int Rows_query_log_event::do_apply_event(Relay_log_info const *rli) { DBUG_ENTER("Rows_query_log_event::do_apply_event"); - DBUG_ASSERT(rli->info_thd == thd); + DBUG_ASSERT(rli->info_thd == thd || rli->is_parallel_exec()); /* Set query for writing Rows_query log event into binlog later.*/ thd->set_query(m_rows_query, (uint32) strlen(m_rows_query)); DBUG_RETURN(0); === modified file 'sql/log_event.h' --- a/sql/log_event.h 2010-12-08 00:33:48 +0000 +++ b/sql/log_event.h 2010-12-16 21:41:45 +0000 @@ -1231,6 +1231,9 @@ public: get_type_code() == PRE_GA_WRITE_ROWS_EVENT || get_type_code() == PRE_GA_UPDATE_ROWS_EVENT|| get_type_code() == PRE_GA_DELETE_ROWS_EVENT|| + + get_type_code() == ROWS_QUERY_LOG_EVENT || /* todo: make parallel */ + get_type_code() == INCIDENT_EVENT; } === modified file 'sql/rpl_rli.cc' --- a/sql/rpl_rli.cc 2010-12-15 17:46:05 +0000 +++ b/sql/rpl_rli.cc 2010-12-16 22:00:47 +0000 @@ -1102,12 +1102,22 @@ void Relay_log_info::cleanup_context(THD { trans_rollback_stmt(thd); // if a "statement transaction" trans_rollback(thd); // if a "real transaction" + } + /* + MTS W/a for Rows_query_log_event. + Cleanup of rows_query_ev at the end of the current statement. + + todo: move handle_rows_query_log_event() cleanup logics into this method + inconditionally. + */ + if (error || is_parallel_exec()) if (rows_query_ev) { delete rows_query_ev; rows_query_ev= NULL; + info_thd->set_query(NULL, 0); } - } + if (!is_parallel_exec() || thd == info_thd) m_table_map.clear_tables(); else === modified file 'sql/rpl_rli.h' --- a/sql/rpl_rli.h 2010-12-15 17:46:05 +0000 +++ b/sql/rpl_rli.h 2010-12-16 22:00:47 +0000 @@ -390,7 +390,7 @@ public: uint tables_to_lock_count; /* RBR: Count of tables to lock */ table_mapping m_table_map; /* RBR: Mapping table-id to table */ /* RBR: Record Rows_query log event */ - Rows_query_log_event* rows_query_ev; + volatile Rows_query_log_event* rows_query_ev; // mts w/a makes it volatile bool get_table_data(TABLE *table_arg, table_def **tabledef_var, TABLE **conv_table_var) const { @@ -449,6 +449,7 @@ public: DYNAMIC_ARRAY curr_group_da; // deferred array to hold partition-info-free events bool curr_group_seen_begin; // current group started with B-event or not bool run_query_in_parallel; // Query's default db not the actual db as part + bool curr_group_isolated; // Trans is exec:d by Worker but in exclusive env volatile ulong mts_wqs_underrun_w_id; // Id of a Worker whose queue is getting empty volatile long mts_wqs_overrun; // W to incr and decr long mts_worker_underrun_level; // percent of WQ size at which Worker claims hungry === modified file 'sql/rpl_rli_pdb.cc' --- a/sql/rpl_rli_pdb.cc 2010-12-15 17:46:05 +0000 +++ b/sql/rpl_rli_pdb.cc 2010-12-16 22:00:47 +0000 @@ -705,7 +705,8 @@ void* circular_buffer_queue::head_queue( } /** - two index comparision. + two index comparision to determine which of the two + is ordered first. @note The caller makes sure the args are within the valid range, incl cases the queue is empty or full. @@ -716,6 +717,8 @@ void* circular_buffer_queue::head_queue( */ bool circular_buffer_queue::gt(ulong i, ulong k) { + DBUG_ASSERT(i < s && k < s); + if (i >= e) if (k >= e) return i > k; @@ -766,7 +769,7 @@ ulong Slave_committed_queue::move_queue_ break; /* the head is not even assigned */ get_dynamic(ws, (uchar *) &w_i, ptr_g->worker_id); - if (gt(i, w_i->last_group_done_index)) + if (w_i->last_group_done_index == s || gt(i, w_i->last_group_done_index)) break; /* gap at i'th */ // memorize the last met group_relay_log_name @@ -818,7 +821,7 @@ ulong Slave_committed_queue::move_queue_ } -int wait_for_workers_to_finish(Relay_log_info const *rli) +int wait_for_workers_to_finish(Relay_log_info const *rli, Slave_worker *ignore) { uint ret= 0; HASH *hash= &mapping_db_to_worker; @@ -837,7 +840,13 @@ int wait_for_workers_to_finish(Relay_log entry= (db_worker*) my_hash_element(hash, i); DBUG_ASSERT(entry); - + + if (ignore && entry->worker == ignore) + { + mysql_mutex_unlock(&slave_worker_hash_lock); + continue; + } + if (entry->usage > 0) { sprintf(wait_info, info_format, entry->worker->id, entry->db); === modified file 'sql/rpl_rli_pdb.h' --- a/sql/rpl_rli_pdb.h 2010-12-15 17:46:05 +0000 +++ b/sql/rpl_rli_pdb.h 2010-12-16 22:00:47 +0000 @@ -25,8 +25,9 @@ bool init_hash_workers(ulong slave_paral void destroy_hash_workers(); Slave_worker *get_slave_worker(const char *dbname, Relay_log_info *rli); Slave_worker *get_least_occupied_worker(DYNAMIC_ARRAY *workers); +int wait_for_workers_to_finish(Relay_log_info const *rli, + Slave_worker *ignore= NULL); bool critical_worker(Relay_log_info *rli); -int wait_for_workers_to_finish(Relay_log_info const *rli); #define SLAVE_WORKER_QUEUE_SIZE 8096 #define SLAVE_INIT_DBS_IN_GROUP 4 // initial allocation for CGEP dynarray === modified file 'sql/rpl_slave.cc' --- a/sql/rpl_slave.cc 2010-12-15 17:46:05 +0000 +++ b/sql/rpl_slave.cc 2010-12-16 22:00:47 +0000 @@ -2817,27 +2817,6 @@ int apply_event_and_update_pos(Log_event else mysql_mutex_unlock(&rli->data_lock); -#ifndef DBUG_OFF - /* - This only prints information to the debug trace. - - TODO: Print an informational message to the error log? - */ - static const char *const explain[] = { - // EVENT_SKIP_NOT, - "not skipped", - // EVENT_SKIP_IGNORE, - "skipped because event should be ignored", - // EVENT_SKIP_COUNT - "skipped because event skip counter was non-zero" - }; - DBUG_PRINT("info", ("OPTION_BEGIN: %d; IN_STMT: %d", - test(thd->variables.option_bits & OPTION_BEGIN), - rli->get_flag(Relay_log_info::IN_STMT))); - DBUG_PRINT("skip_event", ("%s event was %s", - ev->get_type_str(), explain[reason])); -#endif - DBUG_PRINT("info", ("apply_event error = %d", exec_res)); if (exec_res == 0) { @@ -2854,13 +2833,51 @@ int apply_event_and_update_pos(Log_event */ int error= 0; if (skip_event || - !rli->is_parallel_exec() || - ev->only_sequential_exec(rli->run_query_in_parallel, - ev->ends_group() ? - rli->curr_group_is_parallel : - rli->curr_group_seen_begin)) + (!rli->is_parallel_exec() || + !rli->curr_group_is_parallel)) { + DBUG_ASSERT(skip_event || !rli->is_parallel_exec() || + !rli->curr_group_is_parallel || + (ev->only_sequential_exec(rli->run_query_in_parallel, + (rli->curr_group_seen_begin || + rli->last_assigned_worker != NULL)) + && !rli->curr_group_seen_begin)); +#ifndef DBUG_OFF + /* + This only prints information to the debug trace. + + TODO: Print an informational message to the error log? + */ + static const char *const explain[] = { + // EVENT_SKIP_NOT, + "not skipped", + // EVENT_SKIP_IGNORE, + "skipped because event should be ignored", + // EVENT_SKIP_COUNT + "skipped because event skip counter was non-zero" + }; + DBUG_PRINT("info", ("OPTION_BEGIN: %d; IN_STMT: %d", + test(thd->variables.option_bits & OPTION_BEGIN), + rli->get_flag(Relay_log_info::IN_STMT))); + DBUG_PRINT("skip_event", ("%s event was %s", + ev->get_type_str(), explain[reason])); +#endif + error= ev->update_pos(rli); + +#ifndef DBUG_OFF + DBUG_PRINT("info", ("update_pos error = %d", error)); + if (!rli->belongs_to_client()) + { + char buf[22]; + DBUG_PRINT("info", ("group %s %s", + llstr(rli->get_group_relay_log_pos(), buf), + rli->get_group_relay_log_name())); + DBUG_PRINT("info", ("event %s %s", + llstr(rli->get_event_relay_log_pos(), buf), + rli->get_event_relay_log_name())); + } +#endif } else { @@ -2874,28 +2891,15 @@ int apply_event_and_update_pos(Log_event rli->inc_event_relay_log_pos(); } -#ifndef DBUG_OFF - DBUG_PRINT("info", ("update_pos error = %d", error)); - if (!rli->belongs_to_client()) - { - char buf[22]; - DBUG_PRINT("info", ("group %s %s", - llstr(rli->get_group_relay_log_pos(), buf), - rli->get_group_relay_log_name())); - DBUG_PRINT("info", ("event %s %s", - llstr(rli->get_event_relay_log_pos(), buf), - rli->get_event_relay_log_name())); - } -#endif - /* - The update should not fail, so print an error message and - return an error code. - - TODO: Replace this with a decent error message when merged - with BUG#24954 (which adds several new error message). - */ if (error) { + /* + The update should not fail, so print an error message and + return an error code. + + TODO: Replace this with a decent error message when merged + with BUG#24954 (which adds several new error message). + */ char buf[22]; rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR, "It was not possible to update the positions" @@ -3034,25 +3038,18 @@ static int exec_relay_log_event(THD* thd used to read info about the relay log's format; it will be deleted when the SQL thread does not need it, i.e. when this thread terminates. */ - if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT) + // if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT) { - - /* - WL5363 MTS-II: - - ev is deleted by Coordinator when Worker has released the event's item - from its queue. de_queue() just returns the item for extracting ev and - processing, and once that has been done the queue get the item as free. - - if (slave_exec_mode == SLAVE_PARALLEL) + if ((!rli->is_parallel_exec() || + !rli->curr_group_is_parallel) + && ev->get_type_code() != FORMAT_DESCRIPTION_EVENT) { - if (parallel_terminate(ev)) - delete dyn_array the sequence of events comprising the current group; - else push(ev, dyn_array); - } - else - */ - + DBUG_ASSERT(!rli->is_parallel_exec() || + (ev->only_sequential_exec(rli->run_query_in_parallel, + // rli->curr_group_is_parallel + (rli->curr_group_seen_begin || + rli->last_assigned_worker != NULL)) + && !rli->curr_group_seen_begin)); /* MTS: Observation/todo. ROWS_QUERY_LOG_EVENT could be supported easier if @@ -3060,17 +3057,17 @@ static int exec_relay_log_event(THD* thd with rli->cleanup_context() and the rest move into ROWS...::do_apply_event */ - if (thd->variables.binlog_rows_query_log_events) - handle_rows_query_log_event(ev, rli); - - if ((!rli->is_parallel_exec() || - ev->only_sequential_exec(rli->run_query_in_parallel, rli->curr_group_is_parallel)) - && ev->get_type_code() != ROWS_QUERY_LOG_EVENT) // mts TODO: check this case - { + + if (!rli->is_parallel_exec()) + if (thd->variables.binlog_rows_query_log_events) + handle_rows_query_log_event(ev, rli); - DBUG_PRINT("info", ("Deleting the event after it has been executed")); - delete ev; - ev= NULL; + if (ev->get_type_code() != ROWS_QUERY_LOG_EVENT) + { + DBUG_PRINT("info", ("Deleting the event after it has been executed")); + delete ev; + ev= NULL; + } } } @@ -4149,10 +4146,12 @@ int slave_start_workers(Relay_log_info * rli->mts_coordinator_basic_nap= ::opt_mts_coordinator_basic_nap; rli->mts_worker_underrun_level= ::opt_mts_worker_underrun_level; rli->mts_total_groups= 0; - rli->curr_group_seen_begin= 0; + rli->curr_group_seen_begin= FALSE; // initial presumtion, will change + rli->curr_group_is_parallel= TRUE; // initial presumtion, will change + rli->curr_group_isolated= FALSE; rli->run_query_in_parallel= opt_mts_slave_run_query_in_parallel; rli->checkpoint_seqno= 0; - + //rli->worker_bitmap_buf= my_malloc(n/8 + 1,MYF(MY_WME)); for (i= 0; i < n; i++) { if ((error= slave_start_single_worker(rli, i))) @@ -4239,7 +4238,7 @@ void slave_stop_workers(Relay_log_info * delete_dynamic(&rli->least_occupied_workers); // least occupied delete_dynamic(&rli->curr_group_da); // GCDA delete_dynamic(&rli->curr_group_assigned_parts); // GCAP - + //my_free(rli->worker_bitmap_buf); rli->deinit_workers(); } --===============1876489127== 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: cb660539bfeae375316b0f7108d4f582f34ba0d7 # timestamp: 2010-12-17 00:01:48 +0200 # base_revision_id: alfranio.correia@stripped\ # 6o6bfpmlwkw3ecfs # # Begin bundle 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 wu5IpwoSAniiYmA= --===============1876489127==--