From: Andrei Elkin Date: December 2 2010 6:13pm Subject: bzr push into mysql-next-mr-wl5569 branch (andrei.elkin:3225) WL#5569 List-Archive: http://lists.mysql.com/commits/125843 Message-Id: <201012021814.oB2IE5ZB007620@mysql1000.dsl.inet.fi> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0035748803==" --===============0035748803== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 3225 Andrei Elkin 2010-12-02 [merge] manual merge to wl#5569 tree added: sql/dynamic_ids.cc renamed: sql/server_ids.h => sql/dynamic_ids.h modified: .bzr-mysql/default.conf mysql-test/suite/rpl/t/rpl_parallel.test sql/CMakeLists.txt sql/Makefile.am sql/log_event.cc sql/rpl_info_dummy.cc sql/rpl_info_dummy.h 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_mi.cc sql/rpl_mi.h sql/rpl_rli.cc sql/rpl_rli.h sql/rpl_rli_pdb.cc sql/rpl_rli_pdb.h sql/rpl_slave.cc sql/dynamic_ids.h === modified file 'mysql-test/extra/rpl_tests/rpl_parallel_load.test' --- a/mysql-test/extra/rpl_tests/rpl_parallel_load.test 2010-11-20 17:23:42 +0000 +++ b/mysql-test/extra/rpl_tests/rpl_parallel_load.test 2010-12-02 17:46:46 +0000 @@ -1,19 +1,13 @@ # -# This is a load generator to call from rpl_parallel and rpl_serial tests +# This is a load generator to call from rpl_parallel and rpl_sequential tests # -# concurrency parameter. -# Optimally @@global.slave_parallel_workers should be set to -# -# number of CPU:s or cores - 0|1 -# The default is 4. -# - -let $workers = `select @@global.slave_parallel_workers`; # # load volume parameter # + let $iter = 2000; +let $databases = 4; connection slave; @@ -69,7 +63,7 @@ delimiter ;| # delimiter ;| -let $i = $workers + 1; +let $i = $databases + 1; while($i) { let $i1 = $i; @@ -103,7 +97,7 @@ sync_slave_with_master; --disable_query_log --disable_result_log -let $i = $workers + 1; +let $i = $databases + 1; while($i) { let $i1 = $i; @@ -136,7 +130,7 @@ connection master; # the extra ts col on slave is effective only with the STMT format (todo: bug-report) set @save.binlog_format= @@session.binlog_format; set @@session.binlog_format=STATEMENT; -let $i = $workers + 1; +let $i = $databases + 1; while($i) { let $i1 = $i; @@ -159,7 +153,7 @@ connection master; while ($iter) { - let $i = $workers + 1; + let $i = $databases + 1; while ($i) { @@ -188,7 +182,7 @@ connection master; # terminal timestamp to record -let $i = $workers + 1; +let $i = $databases + 1; set @save.binlog_format= @@session.binlog_format; set @@session.binlog_format=STATEMENT; while($i) @@ -209,7 +203,7 @@ set @@session.binlog_format= @save.binlo connection slave; ## todo: record start and end time of appying to compare times of -# parallel and serial execution. +# parallel and sequential execution. --disable_query_log --disable_result_log @@ -243,11 +237,11 @@ select time_to_sec(@m_1) - time_to_sec(@ # debug: pre diff check-out --disable_result_log --disable_query_log -###select sleep(9999); +##select sleep(9999); --enable_result_log --enable_query_log -let $i = $workers + 1; +let $i = $databases + 1; while($i) { let $i1 = $i; @@ -266,7 +260,7 @@ while($i) # debug: pre diff check-out --disable_result_log --disable_query_log -###select sleep(9999); +##select sleep(9999); --enable_result_log --enable_query_log @@ -276,7 +270,7 @@ connection master; --disable_query_log --disable_result_log -let $i = $workers + 1; +let $i = $databases + 1; while($i) { let $i1 = $i; === modified file 'mysql-test/suite/rpl/r/rpl_parallel.result' --- a/mysql-test/suite/rpl/r/rpl_parallel.result 2010-09-17 23:40:11 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel.result 2010-12-02 17:46:46 +0000 @@ -4,11 +4,10 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -set @save.slave_exec_mode= @@global.slave_exec_mode; -set @@global.slave_exec_mode = 'Parallel'; -select @@global.slave_exec_mode like 'Parallel' as 'one'; -one -1 +set @save.slave_parallel_workers= @@global.slave_parallel_workers; +select @@global.slave_parallel_workers as 'non-zero means parallel'; +non-zero means parallel +4 call mtr.add_suppression('Slave: Error dropping database'); include/stop_slave.inc start slave; @@ -27,4 +26,4 @@ Comparing tables master:test3.tm_nk and 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 -set @@global.slave_exec_mode= @save.slave_exec_mode; +set @@global.slave_parallel_workers= @save.slave_parallel_workers; === 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-01 17:08:21 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel_conf_limits.result 2010-12-02 17:46:46 +0000 @@ -6,26 +6,26 @@ drop table if exists t1,t2,t3,t4,t5,t6,t start slave; 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_exec_mode= @@global.slave_exec_mode; -set @@global.slave_exec_mode = 'Parallel'; +set @save.slave_parallel_workers= @@global.slave_parallel_workers; +set @@global.slave_parallel_workers= 4; set @save_mts_slave_worker_queue_len_max= @@global.mts_slave_worker_queue_len_max; set @@global.mts_slave_worker_queue_len_max= 5; include/start_slave.inc -create database d1; -create table d1.t1 (a int auto_increment primary key) engine=innodb; +create database d0; +create table d0.t1 (a int auto_increment primary key) engine=innodb; select sleep(2); sleep(2) 0 begin; -insert into d1.t1 set a=null; +insert into d0.t1 set a=null; begin; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; commit; *** Coordinator must be waiting a for Worker to process its queue *** rollback; @@ -34,14 +34,161 @@ include/stop_slave.inc set @save_mts_pending_jobs_size_max = @@global.mts_pending_jobs_size_max; set @@global.mts_pending_jobs_size_max= 1024; include/start_slave.inc -create table d1.t2 (a int auto_increment primary key, b text null) engine=innodb; +create table d0.t2 (a int auto_increment primary key, b text null) engine=innodb; begin; -insert into d1.t2 set a= 1; +insert into d0.t2 set a= 1; begin; commit; *** Coordinator must be waiting for Workers have released pending events mem *** rollback; set @@global.mts_pending_jobs_size_max= @save_mts_pending_jobs_size_max; +set @save.mts_partition_hash_soft_max= @@global.mts_partition_hash_soft_max; +set @@global.mts_partition_hash_soft_max= 0; +create database d16; +create table d16.t1 (a int auto_increment primary key) engine=innodb; +create database d15; +create table d15.t1 (a int auto_increment primary key) engine=innodb; +create database d14; +create table d14.t1 (a int auto_increment primary key) engine=innodb; +create database d13; +create table d13.t1 (a int auto_increment primary key) engine=innodb; +create database d12; +create table d12.t1 (a int auto_increment primary key) engine=innodb; +create database d11; +create table d11.t1 (a int auto_increment primary key) engine=innodb; +create database d10; +create table d10.t1 (a int auto_increment primary key) engine=innodb; +create database d9; +create table d9.t1 (a int auto_increment primary key) engine=innodb; +create database d8; +create table d8.t1 (a int auto_increment primary key) engine=innodb; +create database d7; +create table d7.t1 (a int auto_increment primary key) engine=innodb; +create database d6; +create table d6.t1 (a int auto_increment primary key) engine=innodb; +create database d5; +create table d5.t1 (a int auto_increment primary key) engine=innodb; +create database d4; +create table d4.t1 (a int auto_increment primary key) engine=innodb; +create database d3; +create table d3.t1 (a int auto_increment primary key) engine=innodb; +create database d2; +create table d2.t1 (a int auto_increment primary key) engine=innodb; +create database d1; +create table d1.t1 (a int auto_increment primary key) engine=innodb; +begin; +insert into d16.t1 set a=null; +insert into d16.t1 set a=null; +insert into d16.t1 set a=null; +insert into d16.t1 set a=null; +commit; +begin; +insert into d15.t1 set a=null; +insert into d15.t1 set a=null; +insert into d15.t1 set a=null; +insert into d15.t1 set a=null; +commit; +begin; +insert into d14.t1 set a=null; +insert into d14.t1 set a=null; +insert into d14.t1 set a=null; +insert into d14.t1 set a=null; +commit; +begin; +insert into d13.t1 set a=null; +insert into d13.t1 set a=null; +insert into d13.t1 set a=null; +insert into d13.t1 set a=null; +commit; +begin; +insert into d12.t1 set a=null; +insert into d12.t1 set a=null; +insert into d12.t1 set a=null; +insert into d12.t1 set a=null; +commit; +begin; +insert into d11.t1 set a=null; +insert into d11.t1 set a=null; +insert into d11.t1 set a=null; +insert into d11.t1 set a=null; +commit; +begin; +insert into d10.t1 set a=null; +insert into d10.t1 set a=null; +insert into d10.t1 set a=null; +insert into d10.t1 set a=null; +commit; +begin; +insert into d9.t1 set a=null; +insert into d9.t1 set a=null; +insert into d9.t1 set a=null; +insert into d9.t1 set a=null; +commit; +begin; +insert into d8.t1 set a=null; +insert into d8.t1 set a=null; +insert into d8.t1 set a=null; +insert into d8.t1 set a=null; +commit; +begin; +insert into d7.t1 set a=null; +insert into d7.t1 set a=null; +insert into d7.t1 set a=null; +insert into d7.t1 set a=null; +commit; +begin; +insert into d6.t1 set a=null; +insert into d6.t1 set a=null; +insert into d6.t1 set a=null; +insert into d6.t1 set a=null; +commit; +begin; +insert into d5.t1 set a=null; +insert into d5.t1 set a=null; +insert into d5.t1 set a=null; +insert into d5.t1 set a=null; +commit; +begin; +insert into d4.t1 set a=null; +insert into d4.t1 set a=null; +insert into d4.t1 set a=null; +insert into d4.t1 set a=null; +commit; +begin; +insert into d3.t1 set a=null; +insert into d3.t1 set a=null; +insert into d3.t1 set a=null; +insert into d3.t1 set a=null; +commit; +begin; +insert into d2.t1 set a=null; +insert into d2.t1 set a=null; +insert into d2.t1 set a=null; +insert into d2.t1 set a=null; +commit; +begin; +insert into d1.t1 set a=null; +insert into d1.t1 set a=null; +insert into d1.t1 set a=null; +insert into d1.t1 set a=null; +commit; +set @@global.mts_partition_hash_soft_max= @save.mts_partition_hash_soft_max; +drop database d16; +drop database d15; +drop database d14; +drop database d13; +drop database d12; +drop database d11; +drop database d10; +drop database d9; +drop database d8; +drop database d7; +drop database d6; +drop database d5; +drop database d4; +drop database d3; +drop database d2; drop database d1; +drop database d0; drop view coord_wait_list; -set @@global.slave_exec_mode= @save.slave_exec_mode; +set @@global.slave_parallel_workers= @save.slave_parallel_workers; === modified file 'mysql-test/suite/rpl/r/rpl_parallel_conflicts.result' --- a/mysql-test/suite/rpl/r/rpl_parallel_conflicts.result 2010-12-01 17:08:21 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel_conflicts.result 2010-12-02 17:46:46 +0000 @@ -6,8 +6,8 @@ drop table if exists t1,t2,t3,t4,t5,t6,t start slave; 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_exec_mode= @@global.slave_exec_mode; -set @@global.slave_exec_mode = 'Parallel'; +set @save.slave_parallel_workers= @@global.slave_parallel_workers; +set @@global.slave_parallel_workers= 4; include/start_slave.inc create database d1; create database d2; @@ -75,5 +75,5 @@ drop database d1; drop database d2; drop database d3; drop view coord_wait_list; -set @@global.slave_exec_mode= @save.slave_exec_mode; +set @@global.slave_parallel_workers= @save.slave_parallel_workers; *** End of the tests *** === modified file 'mysql-test/suite/rpl/r/rpl_parallel_start_stop.result' --- a/mysql-test/suite/rpl/r/rpl_parallel_start_stop.result 2010-11-20 17:23:42 +0000 +++ b/mysql-test/suite/rpl/r/rpl_parallel_start_stop.result 2010-12-02 17:46:46 +0000 @@ -8,8 +8,8 @@ create view worker_proc_list as SELECT i where state like 'Waiting for an event from sql thread%'; create view coord_proc_list as SELECT id from Information_Schema.processlist where state like 'Slave has read all relay log%'; include/stop_slave.inc -set @save.slave_exec_mode= @@global.slave_exec_mode; -set @@global.slave_exec_mode = 'Parallel'; +set @save.slave_parallel_workers= @@global.slave_parallel_workers; +set @@global.slave_parallel_workers= 4; include/start_slave.inc select min(id) from worker_proc_list into @w_id; kill query @w_id; @@ -26,5 +26,5 @@ include/start_slave.inc drop table t1; drop view worker_proc_list; drop view coord_proc_list; -set @@global.slave_exec_mode= @save.slave_exec_mode; +set @@global.slave_parallel_workers= @save.slave_parallel_workers; end of the tests === renamed file 'mysql-test/suite/rpl/r/rpl_serial.result' => 'mysql-test/suite/rpl/r/rpl_sequential.result' --- a/mysql-test/suite/rpl/r/rpl_serial.result 2010-09-17 23:40:11 +0000 +++ b/mysql-test/suite/rpl/r/rpl_sequential.result 2010-12-02 17:46:46 +0000 @@ -4,10 +4,10 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -set @@global.slave_exec_mode = default; -select @@global.slave_exec_mode not like 'Parallel' as 'one'; -one -1 +set @save.slave_parallel_workers= 0; +select @@global.slave_parallel_workers as 'zero'; +zero +0 call mtr.add_suppression('Slave: Error dropping database'); include/stop_slave.inc start slave; === modified file 'mysql-test/suite/rpl/t/rpl_parallel-slave.opt' --- a/mysql-test/suite/rpl/t/rpl_parallel-slave.opt 2010-11-23 09:03:37 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel-slave.opt 2010-12-02 17:46:46 +0000 @@ -1 +1,2 @@ ---relay-log-info-repository=FILE +--relay-log-info-repository=FILE --slave-parallel-workers=4 + === modified file 'mysql-test/suite/rpl/t/rpl_parallel.test' --- a/mysql-test/suite/rpl/t/rpl_parallel.test 2010-12-02 10:32:04 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel.test 2010-12-02 18:13:12 +0000 @@ -2,13 +2,13 @@ # WL#5563 Prototype for Parallel Slave with db name partitioning. # # The test checks correctness of replication and is designed for -# benchmarking and comparision with results of its serial -# counterpart rpl_serial.test. +# benchmarking and comparision with results of its sequential +# counterpart rpl_sequential.test. # Both tests leave mysqld.2/data/test/delta.out file # that contains a row with two columns. # 1. the duration (in seconds) of execution on the master # 2. the duration of execution on the slave -# The 2nd column of the rpl_parallel can be compared with the 2nd of rpl_serial.test. +# The 2nd column of the rpl_parallel can be compared with the 2nd of rpl_sequential.test. # # The duration recorded in the file accounts the SQL thread/workers work. # That is benchmarking on the slave side is effectively started with @@ -28,21 +28,21 @@ # find /dev/shm/var1 -name delta.out -exec cat {} \; | cat >> delta.$slave.log; # done # -# mysql-test$ slave=serial; ... +# mysql-test$ slave=sequential; ... # -# In the end there will be mysql-test/delta.{parallel,serial}.log files. +# In the end there will be mysql-test/delta.{parallel,sequential}.log files. # source include/master-slave.inc; source include/have_binlog_format_row.inc; connection slave; -set @save.slave_exec_mode= @@global.slave_exec_mode; -set @@global.slave_exec_mode = 'Parallel'; -select @@global.slave_exec_mode like 'Parallel' as 'one'; +set @save.slave_parallel_workers= @@global.slave_parallel_workers; +select @@global.slave_parallel_workers as 'non-zero means parallel'; +let $workers = `select @@global.slave_parallel_workers`; connection master; source extra/rpl_tests/rpl_parallel_load.test; connection slave; -set @@global.slave_exec_mode= @save.slave_exec_mode; +set @@global.slave_parallel_workers= @save.slave_parallel_workers; === 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-01 17:08:21 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel_conf_limits.test 2010-12-02 17:46:46 +0000 @@ -15,8 +15,8 @@ create view coord_wait_list as SELECT i # restart in Parallel source include/stop_slave.inc; -set @save.slave_exec_mode= @@global.slave_exec_mode; -set @@global.slave_exec_mode = 'Parallel'; +set @save.slave_parallel_workers= @@global.slave_parallel_workers; +set @@global.slave_parallel_workers= 4; # max len of WQ @@ -26,32 +26,32 @@ source include/start_slave.inc; connection master; -create database d1; -create table d1.t1 (a int auto_increment primary key) engine=innodb; +create database d0; +create table d0.t1 (a int auto_increment primary key) engine=innodb; connection slave; select sleep(2); begin; -insert into d1.t1 set a=null; # lock a row that master has inserted into +insert into d0.t1 set a=null; # lock a row that master has inserted into connection master; begin; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; -insert into d1.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; +insert into d0.t1 set a=null; commit; -let $d1_t1_count=`select count(*) from d1.t1`; +let $d0_t1_count=`select count(*) from d0.t1`; connection slave; @@ -63,8 +63,8 @@ source include/wait_until_rows_count.inc rollback; -let $count= $d1_t1_count; -let $table= d1.t1; +let $count= $d0_t1_count; +let $table= d0.t1; source include/wait_until_rows_count.inc; # cleanup of the max len @@ -85,7 +85,7 @@ eval set @@global.mts_pending_jobs_size_ source include/start_slave.inc; connection master; -create table d1.t2 (a int auto_increment primary key, b text null) engine=innodb; +create table d0.t2 (a int auto_increment primary key, b text null) engine=innodb; connection slave; @@ -97,7 +97,7 @@ select sleep(2); --enable_query_log begin; -insert into d1.t2 set a= 1; +insert into d0.t2 set a= 1; # master trans structure aims at testing C's wait loop @@ -107,23 +107,23 @@ connection master; begin; --disable_query_log - eval insert into d1.t2 set a= 1, b= REPEAT('b', 1); + eval insert into d0.t2 set a= 1, b= REPEAT('b', 1); while ($i_loop) { - eval insert into d1.t2 set b= REPEAT('b', 1); - eval insert into d1.t2 set b= REPEAT('b', 1); - eval insert into d1.t2 set b= REPEAT('b', 1); - eval insert into d1.t2 set b= REPEAT('b', 1); - eval insert into d1.t2 set b= REPEAT('b', 1); - eval insert into d1.t2 set b= REPEAT('b', 1); - eval insert into d1.t2 set b= REPEAT('b', 2* $mts_max_q_size/3); + eval insert into d0.t2 set b= REPEAT('b', 1); + eval insert into d0.t2 set b= REPEAT('b', 1); + eval insert into d0.t2 set b= REPEAT('b', 1); + eval insert into d0.t2 set b= REPEAT('b', 1); + eval insert into d0.t2 set b= REPEAT('b', 1); + eval insert into d0.t2 set b= REPEAT('b', 1); + eval insert into d0.t2 set b= REPEAT('b', 2* $mts_max_q_size/3); dec $i_loop; } --enable_query_log commit; -let $d1_t2_count=`select count(*) from d1.t2`; +let $d0_t2_count=`select count(*) from d0.t2`; connection slave; @@ -135,13 +135,77 @@ source include/wait_until_rows_count.inc rollback; -let $count= $d1_t2_count; -let $table= d1.t2; +let $count= $d0_t2_count; +let $table= d0.t2; source include/wait_until_rows_count.inc; # cleanup of the max len set @@global.mts_pending_jobs_size_max= @save_mts_pending_jobs_size_max; +# +# Number of records in the mts partition hash below which +# entries with zero usage are tolerated. +# The test ensures slave's stable execution. +# + +# force eager garbage collecting +set @save.mts_partition_hash_soft_max= @@global.mts_partition_hash_soft_max; +set @@global.mts_partition_hash_soft_max= 0; + +let $databases= 16; + +connection master; + +let $i= $databases; +while ($i) +{ + eval create database d$i; + eval create table d$i.t1 (a int auto_increment primary key) engine=innodb; + dec $i; +} + +# loading slave with $databases number of parallelizable transaction +# each leaving a dummy record after is completed on the slave + +let $i= $databases; +while ($i) +{ + begin; + eval insert into d$i.t1 set a=null; + eval insert into d$i.t1 set a=null; + eval insert into d$i.t1 set a=null; + eval insert into d$i.t1 set a=null; + commit; + + dec $i; +} + +# TODO: + +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; + +let $i= $databases; +while ($i) +{ + eval drop database d$i; + dec $i; +} + + +connection slave; +#sync_slave_with_master + # # cleanup @@ -149,7 +213,7 @@ set @@global.mts_pending_jobs_size_max= connection master; -drop database d1; +drop database d0; # sync_slave_with_master @@ -159,6 +223,6 @@ drop view coord_wait_list; --sleep 2 -set @@global.slave_exec_mode= @save.slave_exec_mode; +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-01 17:08:21 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test 2010-12-02 17:46:46 +0000 @@ -46,8 +46,9 @@ create view coord_wait_list as SELECT i source include/stop_slave.inc; -set @save.slave_exec_mode= @@global.slave_exec_mode; -set @@global.slave_exec_mode = 'Parallel'; +set @save.slave_parallel_workers= @@global.slave_parallel_workers; +set @@global.slave_parallel_workers= 4; + source include/start_slave.inc; @@ -61,6 +62,7 @@ create table d2.t1 (a int auto_increment create table d3.t1 (a int auto_increment primary key) engine=innodb; # + # I. Two parallel jobs conflict # # two conflicting jobs to follow @@ -214,7 +216,7 @@ connection slave; #sync_slave_with_master; drop view coord_wait_list; -set @@global.slave_exec_mode= @save.slave_exec_mode; +set @@global.slave_parallel_workers= @save.slave_parallel_workers; --echo *** End of the tests *** === modified file 'mysql-test/suite/rpl/t/rpl_parallel_start_stop.test' --- a/mysql-test/suite/rpl/t/rpl_parallel_start_stop.test 2010-11-25 08:47:39 +0000 +++ b/mysql-test/suite/rpl/t/rpl_parallel_start_stop.test 2010-12-02 17:46:46 +0000 @@ -15,8 +15,9 @@ create view coord_proc_list as SELECT i source include/stop_slave.inc; -set @save.slave_exec_mode= @@global.slave_exec_mode; -set @@global.slave_exec_mode = 'Parallel'; +set @save.slave_parallel_workers= @@global.slave_parallel_workers; +set @@global.slave_parallel_workers= 4; + source include/start_slave.inc; let $count= `select @@global.slave_parallel_workers`; @@ -138,7 +139,7 @@ connection slave; drop view worker_proc_list; drop view coord_proc_list; -set @@global.slave_exec_mode= @save.slave_exec_mode; +set @@global.slave_parallel_workers= @save.slave_parallel_workers; --echo end of the tests === renamed file 'mysql-test/suite/rpl/t/rpl_serial.test' => 'mysql-test/suite/rpl/t/rpl_sequential.test' --- a/mysql-test/suite/rpl/t/rpl_serial.test 2010-09-17 23:40:11 +0000 +++ b/mysql-test/suite/rpl/t/rpl_sequential.test 2010-12-02 17:46:46 +0000 @@ -1,7 +1,7 @@ # # WL#5563 Prototype for Parallel Slave with db name partitioning. # -# The test can be used for benchmarking and comparision with its serial +# The test can be used for benchmarking and comparision with its sequential # counterpart rpl_parallel.test. Read more comments in there. # @@ -9,8 +9,8 @@ source include/master-slave.inc; connection slave; -set @@global.slave_exec_mode = default; -select @@global.slave_exec_mode not like 'Parallel' as 'one'; +set @save.slave_parallel_workers= 0; +select @@global.slave_parallel_workers as 'zero'; connection master; === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2010-12-01 19:15:08 +0000 +++ b/sql/log_event.cc 2010-12-02 18:13:12 +0000 @@ -2218,6 +2218,9 @@ Slave_worker *Log_event::get_slave_worke // the last occupied GAQ's array index rli->gaq->assigned_group_index= rli->gaq->en_queue((void *) &g); + DBUG_ASSERT(((Slave_job_group *) + dynamic_array_ptr(&rli->gaq->Q, rli->gaq->assigned_group_index))-> + group_relay_log_name == NULL); DBUG_ASSERT(rli->gaq->assigned_group_index != (ulong) -1); // gaq must have room DBUG_ASSERT(rli->last_assigned_worker == NULL); if (is_b_event) @@ -2251,6 +2254,9 @@ Slave_worker *Log_event::get_slave_worke { g.worker_id= worker->id; // todo/fixme: think of Slave_worker* here set_dynamic(&rli->gaq->Q, (uchar*) &g, rli->gaq->assigned_group_index); + + DBUG_ASSERT(g.group_relay_log_name == NULL); + } } else // r @@ -2296,6 +2302,9 @@ Slave_worker *Log_event::get_slave_worke ptr_g->group_relay_log_name= (char *) my_malloc(strlen(const_cast(rli)->get_group_relay_log_name()) + 1, MYF(MY_WME)); strcpy(ptr_g->group_relay_log_name, const_cast(rli)->get_group_relay_log_name()); + + DBUG_ASSERT(ptr_g->group_relay_log_name != NULL); + worker->relay_log_change_notified= TRUE; } @@ -2326,6 +2335,7 @@ Slave_worker *Log_event::get_slave_worke return worker; } +// returns the next available! (TODO: incompatible to circurla_buff method!!!) static int en_queue(Slave_jobs_queue *jobs, Slave_job_item *item) { if (jobs->a == jobs->s) @@ -2436,9 +2446,9 @@ void append_item_to_jobs(slave_job_item new_pend_size= rli->mts_pending_jobs_size + ((Log_event*) (job_item->data))->data_written; } + rli->pending_jobs++; rli->mts_pending_jobs_size= new_pend_size; rli->stmt_jobs++; - rli->pending_jobs++; mysql_mutex_unlock(&rli->pending_jobs_lock); @@ -2486,7 +2496,8 @@ void append_item_to_jobs(slave_job_item { mysql_mutex_unlock(&w->jobs_lock); mysql_mutex_lock(&rli->pending_jobs_lock); - rli->pending_jobs--; // roll back of the prev incr + rli->pending_jobs--; // roll back of the prev incr + rli->mts_pending_jobs_size -= new_pend_size; mysql_mutex_unlock(&rli->pending_jobs_lock); } } @@ -2688,6 +2699,8 @@ int slave_worker_exec_job(Slave_worker * if (ev->ends_group() || !w->curr_group_seen_begin) { + DBUG_PRINT("slave_worker_exec_job:", (" commits GAQ index %lu, last committed %lu", ev->mts_group_cnt, w->last_group_done_index)); + w->slave_worker_ends_group(ev->mts_group_cnt, error); /* last done sets post exec */ if (!(ev->get_type_code() == XID_EVENT && w->is_transactional())) w->commit_positions(ev); === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2010-12-01 17:08:21 +0000 +++ b/sql/mysqld.cc 2010-12-02 17:46:46 +0000 @@ -460,7 +460,7 @@ ulong slave_trans_retries; uint slave_net_timeout; ulong slave_exec_mode_options; ulonglong slave_type_conversions_options; -ulong slave_parallel_workers; +ulong opt_slave_parallel_workers; ulong opt_mts_slave_worker_queue_len_max; my_bool slave_local_timestamp_opt; my_bool opt_slave_run_query_in_parallel; === modified file 'sql/mysqld.h' --- a/sql/mysqld.h 2010-12-01 17:08:21 +0000 +++ b/sql/mysqld.h 2010-12-02 17:46:46 +0000 @@ -172,7 +172,7 @@ extern my_bool allow_slave_start; extern LEX_CSTRING reason_slave_blocked; extern ulong slave_trans_retries; extern uint slave_net_timeout; -extern ulong slave_parallel_workers; +extern ulong opt_slave_parallel_workers; extern ulong opt_mts_slave_worker_queue_len_max; extern my_bool slave_local_timestamp_opt; extern my_bool opt_slave_run_query_in_parallel; === modified file 'sql/rpl_rli.cc' --- a/sql/rpl_rli.cc 2010-12-01 19:15:08 +0000 +++ b/sql/rpl_rli.cc 2010-12-02 18:13:12 +0000 @@ -68,7 +68,7 @@ Relay_log_info::Relay_log_info(bool is_s until_log_pos(0), retried_trans(0), tables_to_lock(0), tables_to_lock_count(0), rows_query_ev(NULL), last_event_start_time(0), - this_worker(NULL), slave_worker_is_error(NULL), + this_worker(NULL), slave_parallel_workers(0), sql_delay(0), sql_delay_end(0), m_flags(0) { @@ -85,6 +85,9 @@ Relay_log_info::Relay_log_info(bool is_s mysql_cond_init(key_checkpoint_start_cond, &checkpoint_start_cond, NULL); mysql_cond_init(key_checkpoint_stop_cond, &checkpoint_stop_cond, NULL); relay_log.init_pthread_objects(); + +#if 0 + /* Parallel slave parameters initialization is done regardless whether the feature is or going to be active or not. @@ -126,9 +129,65 @@ Relay_log_info::Relay_log_info(bool is_s MY_MUTEX_INIT_FAST); mysql_cond_init(key_cond_slave_parallel_pend_jobs, &pending_jobs_cond, NULL); my_init_dynamic_array(&workers, sizeof(Slave_worker *), slave_parallel_workers, 4); + +#endif + DBUG_VOID_RETURN; } +/** + The method to invoke at slave threads start +*/ +void Relay_log_info::init_workers(ulong n) +{ + uint wi= 0; + + slave_parallel_workers= n; + /* + Parallel slave parameters initialization is done regardless + whether the feature is or going to be active or not. + */ + trans_jobs= stmt_jobs= pending_jobs= wait_jobs= 0; + + key_mutex_slave_parallel_worker= new PSI_mutex_key[slave_parallel_workers]; + key_cond_slave_parallel_worker= new PSI_cond_key[slave_parallel_workers]; + worker_mutexes= new PSI_mutex_info[slave_parallel_workers]; + worker_conds= new PSI_cond_info[slave_parallel_workers]; + for (wi= 0; wi < slave_parallel_workers; wi++) + { + worker_mutexes[wi].m_key= (PSI_mutex_key *) &(key_mutex_slave_parallel_worker[wi]); + worker_mutexes[wi].m_name= "Slave_worker::jobs_lock"; + worker_mutexes[wi].m_flags= 0; + worker_conds[wi].m_key= (PSI_cond_key *) &(key_cond_slave_parallel_worker[wi]); + worker_conds[wi].m_name= "Slave_worker::jobs_cond"; + worker_conds[wi].m_flags= 0; + } + if (PSI_server) + { + PSI_server->register_mutex("worker", worker_mutexes, + slave_parallel_workers); + PSI_server->register_cond("worker", worker_conds, + slave_parallel_workers); + } + mysql_mutex_init(key_mutex_slave_parallel_pend_jobs, &pending_jobs_lock, + MY_MUTEX_INIT_FAST); + mysql_cond_init(key_cond_slave_parallel_pend_jobs, &pending_jobs_cond, NULL); + my_init_dynamic_array(&workers, sizeof(Slave_worker *), slave_parallel_workers, 4); +} + +/** + The method to invoke at slave threads stop +*/ +void Relay_log_info::deinit_workers() +{ + mysql_mutex_destroy(&pending_jobs_lock); + mysql_cond_destroy(&pending_jobs_cond); + + if (!this_worker) + delete_dynamic(&workers); + slave_parallel_workers= 0; +} + Relay_log_info::~Relay_log_info() { DBUG_ENTER("Relay_log_info::~Relay_log_info"); @@ -139,16 +198,40 @@ Relay_log_info::~Relay_log_info() mysql_cond_destroy(&log_space_cond); relay_log.cleanup(); +#if 0 + mysql_mutex_destroy(&pending_jobs_lock); mysql_cond_destroy(&pending_jobs_cond); if (!this_worker) delete_dynamic(&workers); +#endif + DBUG_VOID_RETURN; } /** + Method is called when MTS coordinator senses the relay-log name + has been changed. + It marks each Worker member with this fact to make an action + at time it will distribute a terminal event of a group to the Worker. + + Worker receives the new name at the group commiting phase + @c Slave_worker::slave_worker_ends_group(). +*/ +void Relay_log_info::reset_notified_relay_log_change() +{ + if (!is_parallel_exec()) + return; + for (uint i= 0; i < workers.elements; i++) + { + Slave_worker *w= *(Slave_worker **) dynamic_array_ptr(&workers, i); + w->relay_log_change_notified= FALSE; + } +} + +/** The method can be run both by C having the Main (coord) rli context and by W having both the main and the Local (worker) rli context. Decision matrix: === modified file 'sql/rpl_rli.h' --- a/sql/rpl_rli.h 2010-12-01 19:15:08 +0000 +++ b/sql/rpl_rli.h 2010-12-02 18:13:12 +0000 @@ -448,8 +448,9 @@ public: Slave_worker* set_this_worker(Slave_worker *w) { return this_worker= w; } Slave_worker* this_worker; // used by w_rli. The cental rli has it as NULL. ulonglong mts_total_groups; // total event groups distributed in current session - volatile Slave_worker* slave_worker_is_error; + bool curr_group_is_parallel; // a mark for Coord to indicate on T-event of the curr group at delete + ulong slave_parallel_workers; // one slave session time number of workers /* A sorted array of Worker current assignements number to provide approximate view on Workers loading. @@ -458,6 +459,26 @@ public: */ DYNAMIC_ARRAY least_occupied_workers; + /* most of allocation in the coordinator rli is there */ + void init_workers(ulong); + + /* counterpart of the init */ + void deinit_workers(); + + /** + returns true if events are to be executed in parallel + */ + inline bool is_parallel_exec() const + { + bool ret= slave_parallel_workers > 0; + + DBUG_ASSERT(!ret || workers.elements > 0); + + return ret; + } + + void reset_notified_relay_log_change(); + /** Helper function to do after statement completion. @@ -618,21 +639,6 @@ public: int32 get_sql_delay() { return sql_delay; } void set_sql_delay(time_t _sql_delay) { sql_delay= _sql_delay; } time_t get_sql_delay_end() { return sql_delay_end; } - /** - mts-II: - returns true if events are to be executed in parallel - todo: - Consider a def SEQUENTIAL := sizeof(worker-pool) == 0 - PARALLEL := sizeof(worker-pool) > 0 - */ - inline bool is_parallel_exec() const - { - return workers.elements > 0 && - // TODO: bug to report!!! - // Sys_vqar_!enum! Slave_exec_mode -> Sys_var_*set* Slave_exec_mode - // bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_PARALLEL) == 1; - slave_exec_mode == SLAVE_EXEC_MODE_PARALLEL; - } private: === modified file 'sql/rpl_rli_pdb.cc' --- a/sql/rpl_rli_pdb.cc 2010-12-02 10:32:04 +0000 +++ b/sql/rpl_rli_pdb.cc 2010-12-02 18:13:12 +0000 @@ -481,8 +481,12 @@ void Slave_worker::slave_worker_ends_gro if (!error) { Slave_job_group *ptr_g= - (Slave_job_group *) - dynamic_array_ptr(&c_rli->gaq->Q, c_rli->gaq->assigned_group_index); + (Slave_job_group *) dynamic_array_ptr(&c_rli->gaq->Q, gaq_idx); + + // first ever group must have relay log name + DBUG_ASSERT(last_group_done_index != c_rli->gaq->s || + ptr_g->group_relay_log_name != NULL); + if (ptr_g->group_relay_log_name != NULL) { // memorizing a new relay-log file name @@ -575,6 +579,9 @@ ulong circular_buffer_queue::de_queue(uc return ret; } +/** + @return the used index at success or -1 when queue is full +*/ ulong circular_buffer_queue::en_queue(void *item) { ulong ret; === modified file 'sql/rpl_slave.cc' --- a/sql/rpl_slave.cc 2010-12-02 13:16:13 +0000 +++ b/sql/rpl_slave.cc 2010-12-02 18:13:12 +0000 @@ -1042,7 +1042,7 @@ static bool sql_slave_killed(THD* thd, R DBUG_ASSERT(rli->info_thd == thd || thd->slave_thread); DBUG_ASSERT(rli->slave_running == 1 || thd->slave_thread);// tracking buffer overrun - if (abort_loop || thd->killed || rli->abort_slave || rli->slave_worker_is_error) + if (abort_loop || thd->killed || rli->abort_slave) { if (thd->transaction.all.modified_non_trans_table && rli->is_in_group()) { @@ -2672,10 +2672,12 @@ int apply_event_and_update_pos(Log_event if ((rli->curr_group_is_parallel == FALSE && !(ev->get_type_code() == XID_EVENT && rli->is_transactional())) || skip_event) + error= ev->update_pos(rli); /* Temporarily placed here /Alfranio */ - checkpoint_routine(rli); + if (rli->is_parallel_exec()) + checkpoint_routine(rli); #ifndef DBUG_OFF DBUG_PRINT("info", ("update_pos error = %d", error)); @@ -3552,7 +3554,6 @@ pthread_handler_t handle_slave_worker(vo if (error) { - rli->slave_worker_is_error= w; mysql_mutex_lock(&rli->info_thd->LOCK_thd_data); rli->info_thd->awake(THD::KILL_QUERY); // notify Crdn mysql_mutex_unlock(&rli->info_thd->LOCK_thd_data); @@ -3824,12 +3825,19 @@ int slave_start_workers(Relay_log_info * uint i; int error= 0; + if (n == 0) + return error; + + // RLI constructor time alloc/init + + rli->init_workers(n); + // CGAP dynarray holds id:s of partitions of the Current being executed Group my_init_dynamic_array(&rli->curr_group_assigned_parts, 1 + NAME_LEN + 1, SLAVE_INIT_DBS_IN_GROUP, 1); rli->last_assigned_worker= NULL; /* associated with curr_group_assigned */ my_init_dynamic_array(&rli->curr_group_da, sizeof(Log_event*), 8, 2); - // Least_occupied_workers array - my_init_dynamic_array(&rli->least_occupied_workers, sizeof(ulong), n, 0); + // Least_occupied_workers array to hold items size of Slave_jobs_queue::len + my_init_dynamic_array(&rli->least_occupied_workers, sizeof(ulong), n, 0); // GAQ queue holds seqno:s of scheduled groups. C polls workers in // @c lwm_checkpoint_period to update GAQ (see @c next_event()) @@ -3850,7 +3858,6 @@ 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->slave_worker_is_error= NULL; rli->curr_group_seen_begin= NULL; rli->run_query_in_parallel= opt_slave_run_query_in_parallel; for (i= 0; i < n; i++) @@ -3884,10 +3891,8 @@ void slave_stop_workers(Relay_log_info * int i; THD *thd= rli->info_thd; - /*if (rli->is_parallel_exec()) - { - slave_stop_checkpoint(rli); - }*/ + if (rli->workers.elements == 0) + return; for (i= rli->workers.elements - 1; i >= 0; i--) { @@ -3947,6 +3952,8 @@ 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 + + rli->deinit_workers(); } /** @@ -3993,7 +4000,7 @@ pthread_handler_t handle_slave_sql(void pthread_detach_this_thread(); /* mts-II: starting the worker pool */ - if (slave_start_workers(rli, slave_parallel_workers) != 0) + if (slave_start_workers(rli, opt_slave_parallel_workers) != 0) goto err; if (init_slave_thread(thd, SLAVE_THD_SQL)) @@ -5273,9 +5280,10 @@ static Log_event* next_event(Relay_log_i llstr(my_b_tell(cur_log),llbuf1), llstr(rli->get_event_relay_log_pos(),llbuf2))); DBUG_ASSERT(my_b_tell(cur_log) >= BIN_LOG_HEADER_SIZE); - DBUG_ASSERT(my_b_tell(cur_log) == rli->get_event_relay_log_pos() || - //bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_PARALLEL) == 1); - slave_exec_mode_options == SLAVE_EXEC_MODE_PARALLEL); // todo: fix slave_exec_mode enum->set + + // TODO: sort out with Alfranio + + DBUG_ASSERT(my_b_tell(cur_log) == rli->get_event_relay_log_pos() || rli->is_parallel_exec()); DBUG_PRINT("info", ("next_event group master %s %lu group relay %s %lu event %s %lu\n", rli->get_group_master_log_name(), @@ -5504,10 +5512,12 @@ static Log_event* next_event(Relay_log_i } /* Reset the relay-log-change-notified status of Slave Workers */ - for (uint i= 0; i < rli->workers.elements; i++) + if (rli->is_parallel_exec()) { - Slave_worker *w= *(Slave_worker **) dynamic_array_ptr(&rli->workers, i); - w->relay_log_change_notified= FALSE; + DBUG_PRINT("info", ("next_event: MTS group relay log changes to %s %lu\n", + rli->get_group_relay_log_name(), + (ulong) rli->get_group_relay_log_pos())); + rli->reset_notified_relay_log_change(); } /* === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2010-11-20 17:23:42 +0000 +++ b/sql/sql_class.h 2010-12-02 17:46:46 +0000 @@ -62,7 +62,6 @@ enum enum_delay_key_write { DELAY_KEY_WR DELAY_KEY_WRITE_ALL }; enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT, SLAVE_EXEC_MODE_IDEMPOTENT, - SLAVE_EXEC_MODE_PARALLEL, SLAVE_EXEC_MODE_LOCAL_TIMESTAMP, SLAVE_EXEC_MODE_LAST_BIT }; enum enum_slave_type_conversions { SLAVE_TYPE_CONVERSIONS_ALL_LOSSY, === modified file 'sql/sys_vars.cc' --- a/sql/sys_vars.cc 2010-12-01 17:08:21 +0000 +++ b/sql/sys_vars.cc 2010-12-02 17:46:46 +0000 @@ -3107,8 +3107,8 @@ static Sys_var_ulong Sys_slave_trans_ret static Sys_var_ulong Sys_slave_parallel_workers( "slave_parallel_workers", "Number of worker threads for executing events in parallel ", - GLOBAL_VAR(slave_parallel_workers), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(0, ULONG_MAX), DEFAULT(4), BLOCK_SIZE(1)); + GLOBAL_VAR(opt_slave_parallel_workers), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1)); static Sys_var_ulong Sys_mts_slave_worker_queue_len_max( "mts_slave_worker_queue_len_max", "Max length of one MTS Worker queue. Presence in the queue indicates " @@ -3130,7 +3130,7 @@ static Sys_var_mybool Sys_slave_run_quer GLOBAL_VAR(opt_slave_run_query_in_parallel), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static Sys_var_ulong Sys_mts_partition_hash_soft_max( - "opt_mts_partition_hash_soft_max", + "mts_partition_hash_soft_max", "Number of records in the mts partition hash below which " "entries with zero usage are tolerated", GLOBAL_VAR(opt_mts_partition_hash_soft_max), CMD_LINE(REQUIRED_ARG), --===============0035748803== 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: c04aebfcb3138b464044e6b98b9cd5dffbddb73e # timestamp: 2010-12-02 20:14:05 +0200 # base_revision_id: andrei.elkin@stripped\ # hq7qqnbwttpl9w5v # # Begin bundle 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 --===============0035748803==--