#!/bin/sh # # Copyright (c) 2006 MySQL AB # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA echo "########################################################################" echo "#" echo "# Test Bug#17332 - changing key_buffer_size on a running server" echo "# can crash under load" echo "#" echo ######################################################################## # # Settings. CAUTION: Paths are not space safe. # # BASEDIR="install directory" # DATADIR="databases directory e.g. $BASEDIR/var" DATADIR="${DATADIR:-$BASEDIR/var}" TREEROOT="${TREEROOT:-$HOME}" MYSQLD="$BASEDIR/libexec/mysqld" MYSQLC="$BASEDIR/bin/mysql" MYSQLA="$BASEDIR/bin/mysqladmin" MYSQLT="$BASEDIR/bin/mysqltest" PORT_1="${MYSQL_TCP_PORT:+--port=$MYSQL_TCP_PORT}" SOCK_1="${MYSQL_UNIX_PORT:+--socket=$MYSQL_UNIX_PORT}" USER_1="-u root -D test" #CLNT_1="-A -v -f" CLNT_1="-A -v --show-warnings" DATA_1="--basedir=$BASEDIR --datadir=$DATADIR" SERV_1="--log-error --core" #SERV_1="$SERV_1 --skip-innodb --skip-ndbcluster" # ######################################################################## # These parameters influence the behaviour of the test: # NUMBER_OF_TABLES=4 CLIENTS_PER_TABLE=4 # #BLOCK_SIZE="1200" # force 1024 bytes cache blocks #BLOCK_SIZE="2200" # force 2048 bytes cache blocks #BLOCK_SIZE="4300" # force 4096 bytes cache blocks BLOCK_SIZE="8400" # force 8192 bytes cache blocks # #CACHE_SIZE="0" # disable key cache #CACHE_SIZE="12288" # force evictions with empty LRU ring (min size for 1K) #CACHE_SIZE="20480" # force evictions with empty LRU ring (min size for 2K) #CACHE_SIZE="36864" # force evictions with empty LRU ring (min size for 4K) #CACHE_SIZE="69632" # force evictions with empty LRU ring (min size for 8K) #CACHE_SIZE="36864" # small cache (for 1K blocks) #CACHE_SIZE="73728" # small cache (for 2K blocks) #CACHE_SIZE="147456" # small cache (for 4K blocks) CACHE_SIZE="294912" # small cache (for 8K blocks) #CACHE_SIZE="8388608" # medium cache # #RESIZE_MEM="0 0" # min/max for disabled resize of disabled cache #RESIZE_MEM="2000 8000" # min/max for enabled resize of disabled cache #RESIZE_MEM="36864 36864" # min/max for disabled resize for 1K blocks #RESIZE_MEM="73728 73728" # min/max for disabled resize for 2K blocks #RESIZE_MEM="147456 147456" # min/max for disabled resize for 4K blocks #RESIZE_MEM="294912 294912" # min/max for disabled resize for 8K blocks #RESIZE_MEM="8388608 8388608" # min/max for disabled resize for medium cache #RESIZE_MEM="0 36864" # min/max for normal resize for 1K blocks #RESIZE_MEM="0 73728" # min/max for normal resize for 2K blocks #RESIZE_MEM="0 147456" # min/max for normal resize for 4K blocks RESIZE_MEM="0 294912" # min/max for normal resize for 8K blocks # RESIZE_BLK="0 3" # min/max for 1K*power(2, X) # # Some machines need a break to cool down. Seconds. # Can be overridden by contents of file "$DATADIR/sleep_time". SLEEP_TIME=60 # ######################################################################## # SERV_1="$SERV_1 --key_cache_block_size=$BLOCK_SIZE" SERV_1="$SERV_1 --key_buffer_size=$CACHE_SIZE" #SERV_1="$SERV_1 --delay-key-write=all" #SERV_1="$SERV_1 --skip-concurrent-insert" # #DBUG_1="--debug=t:d:i:O,$DATADIR/mysqld.trace" #DBUG_1="--debug=d,thrlock:i:O,$DATADIR/mysqld.trace" HOSTNAM="`expr \`uname -n\` : '\([^\.]*\)'`" ERRFILE="$HOSTNAM.err" PIDFILE="$HOSTNAM.pid" ######################################################################## # # Go to DATADIR. # cd "$DATADIR" || exit $? ######################################################################## # # Cleanup. # rm -f *.trace *.err *.pid core* test/#sql* bug17332* test_stop rm -rf tmp/* test -d test || mkdir test test -d tmp || mkdir tmp ######################################################################## # # Functions. sleep_until_pidfile_created () { file="$1" loop="$2" org_time="$2" while [ "$loop" -gt 0 ] do if [ -r "$file" ] then return fi sleep 1 loop="`expr \"$loop\" - 1`" done echo "ERROR: $file was not created in $org_time seconds; Aborting" exit 1; } sleep_until_pidfile_deleted () { file="$1" loop="$2" while [ "$loop" -gt 0 ] do if [ -r "$file" ] then if kill -0 "`cat \"$file\"`" then sleep 1 else break fi else break fi loop="`expr \"$loop\" - 1`" done } ######################################################################## # # Preparing scripts. # cat > bug17332-create.pl <<'EOF' #!/usr/bin/perl -w my $table= $ARGV[0]; print "DROP TABLE IF EXISTS $table;\n"; print "CREATE TABLE $table ("; print " id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,"; print " v1 CHAR(150),"; print " v2 CHAR(150),"; print " v3 CHAR(150),"; print " KEY(id,v1,v2,v3),"; print " KEY(v2,v3,v1),"; print " KEY(v3,v1,v2)"; print " ) ENGINE=MyISAM;\n"; EOF cat > bug17332-worker.pl <<'EOF' #!/usr/bin/perl -w my $table= $ARGV[0]; # # Loop on insert and flush. # for (my $insert= 50; $insert; $insert--) { print "SHOW VARIABLES LIKE '%key\\_%';\n"; print "SHOW STATUS LIKE 'key\\_%';\n"; # # Load keycache. # print "INSERT INTO ${table} (v1,v2,v3) VALUES ('a','b','c')"; for (my $idx= int(rand(512)); $idx > 0; $idx--) { print ",('a','b','c')"; } print ";\n"; # # Miscellaneous operations executed randomly. # if ( $insert % int(rand(5) + 1) == 1 ) { if ( int(rand(7)) == 0 ) { print "UPDATE ${table} SET v1='a', v2='b', v3='c'". "WHERE v2='e';\n"; } else { print "UPDATE ${table} SET v1='d', v2='e', v3='f'". "WHERE id MOD 13 = ". int(rand(13)) .";\n"; } } if ( $insert % int(rand(20) + 1) == 1 ) { if ( int(rand(4)) == 0 ) { print "FLUSH TABLE;\n"; } else { print "FLUSH TABLE ${table};\n"; } } if ( $insert % int(rand(20) + 1) == 1 ) { print "CHECK TABLE ${table};\n"; } if ( $insert % int(rand(20) + 1) == 1 ) { print "CREATE TEMPORARY TABLE tt1". "(KEY(id), KEY(v1,v2,v3)) SELECT * FROM ${table};\n"; print "UPDATE tt1 SET v1='d', v2='e', v3='f'". "WHERE id MOD 13 = ". int(rand(13)) .";\n"; print "DROP TABLE tt1;\n"; } if ( $insert % int(rand(20) + 1) == 1 ) { print "LOAD INDEX INTO CACHE ${table};\n"; } } # # Check table. # if ( int(rand(2)) == 0 ) { print "FLUSH TABLE ${table};\n"; } print "CHECK TABLE ${table};\n"; # # End of test. # print "SHOW VARIABLES LIKE '%key\\_%';\n"; print "SHOW STATUS LIKE 'key\\_%';\n"; print "SELECT 'END OF TEST';\n"; EOF cat > bug17332-resizer.pl <<'EOF' #!/usr/bin/perl -w my $resize_mem_min= $ARGV[0]; my $resize_mem_max= $ARGV[1]; my $resize_blk_min= $ARGV[2]; my $resize_blk_max= $ARGV[3]; my $number_of_tables= $ARGV[4]; my $clients_per_table= $ARGV[5]; my $resize_mem_var= $resize_mem_max - $resize_mem_min + 1; my $resize_blk_var= $resize_blk_max - $resize_blk_min + 1; my $loop_min= 4 * $number_of_tables * $clients_per_table; my $loop_var= 240 * $number_of_tables * $clients_per_table; my $delay_key_write= 0; # # Loop on resize. # for (my $idx= $loop_min + int(rand($loop_var)); $idx; $idx--) { # # Change key_buffer_size in every iteration. # print "SHOW VARIABLES LIKE '%key\\_%';\n"; print "SHOW STATUS LIKE 'key\\_%';\n"; print "SET GLOBAL key_buffer_size=". ($resize_mem_min + int(rand($resize_mem_var))) .";\n"; # # Sometimes sleep after resize # if ( $idx % int(rand(10) + 1) == 1 ) { print "SHOW VARIABLES LIKE '%key\\_%';\n"; print "SHOW STATUS LIKE 'key\\_%';\n"; print "SELECT SLEEP(". int(rand(4) + 1) .");\n"; } # # Sometimes change key_cache_block_size # if ( $idx % int(rand(10) + 1) == 1 ) { print "SHOW VARIABLES LIKE '%key\\_%';\n"; print "SHOW STATUS LIKE 'key\\_%';\n"; my $curr_block_size= 1024 * (1 << ($resize_blk_min + int(rand($resize_blk_var)))); print "SET GLOBAL key_cache_block_size=". $curr_block_size .";\n"; # # Sometimes sleep after resize # if ( $idx % int(rand(4) + 1) == 1 ) { print "SHOW VARIABLES LIKE '%key\\_%';\n"; print "SHOW STATUS LIKE 'key\\_%';\n"; print "SELECT SLEEP(". int(rand(4) + 1) .");\n"; } } # # Sometimes toggle delay_key_write # if ( $idx % int(rand(20) + 1) == 1 ) { print "SHOW VARIABLES LIKE '%key\\_%';\n"; print "SHOW STATUS LIKE 'key\\_%';\n"; $delay_key_write= !$delay_key_write; if ($delay_key_write) { print "SET GLOBAL delay_key_write= ALL;\n"; } else { print "SET GLOBAL delay_key_write= OFF;\n"; } } } print "SHOW VARIABLES LIKE '%key\\_%';\n"; print "SHOW STATUS LIKE 'key\\_%';\n"; print "SELECT 'END OF TEST';\n"; EOF ######################################################################## # # Run in a loop until it fails. # ROUND=1 while : do echo "######################################################################" echo "#" echo "# `date '+%Y-%m-%d %H:%M:%S'` Starting round $ROUND." echo "#" echo "# key_cache_block_size: $BLOCK_SIZE" echo "# key_buffer_size: $CACHE_SIZE" echo "# resize_mem min/max: $RESIZE_MEM" echo "# resize_blk min/max: $RESIZE_BLK" echo echo "######################################################################" echo "#" echo "# Starting database server." # # Use a subshell here, to detach the server. # ( nice "$MYSQLD" --no-defaults $PORT_1 $SOCK_1 $DATA_1 $SERV_1 $DBUG_1 & SERV_1_PID=$! echo "# Process_id $SERV_1_PID" sleep_until_pidfile_created "$PIDFILE" 400 ) echo echo "######################################################################" echo "#" echo "# Creating tables." TABLE_NO="1" while [ "$TABLE_NO" -le "$NUMBER_OF_TABLES" ] do perl bug17332-create.pl "t$TABLE_NO" 2>/dev/null | \ "$MYSQLC" $PORT_1 $SOCK_1 $USER_1 $CLNT_1 \ > "bug17332-$TABLE_NO-0.log" 2>&1 TABLE_NO="`expr \"$TABLE_NO\" + 1`" done sleep 2 echo echo "######################################################################" echo "#" echo "# Flush tables." "$MYSQLA" $PORT_1 $SOCK_1 -u root refresh echo TABLE_NO="1" while [ "$TABLE_NO" -le "$NUMBER_OF_TABLES" ] do CLIENT_NO="1" while [ "$CLIENT_NO" -le "$CLIENTS_PER_TABLE" ] do ( CLIENT_ID="$TABLE_NO-$CLIENT_NO" echo "################################################################" echo "#" echo "# `date '+%Y-%m-%d %H:%M:%S'` Starting client $CLIENT_ID." perl bug17332-worker.pl "t$TABLE_NO" 2>/dev/null | \ "$MYSQLC" $PORT_1 $SOCK_1 $USER_1 $CLNT_1 \ > "bug17332-$CLIENT_ID.log" 2>&1 echo "# `date '+%Y-%m-%d %H:%M:%S'` Client $CLIENT_ID finished" \ "round $ROUND." ) & sleep 2 echo CLIENT_NO="`expr \"$CLIENT_NO\" + 1`" done TABLE_NO="`expr \"$TABLE_NO\" + 1`" done # # There is no use for more than one resizers as only one can be started # from set_var.cc (see key_cache->in_init). # ( echo "################################################################" echo "#" echo "# `date '+%Y-%m-%d %H:%M:%S'` Starting resizer." perl bug17332-resizer.pl $RESIZE_MEM $RESIZE_BLK \ $NUMBER_OF_TABLES $CLIENTS_PER_TABLE 2>/dev/null | \ "$MYSQLC" $PORT_1 $SOCK_1 $USER_1 $CLNT_1 \ > bug17332-0-resizer.log 2>&1 echo "# `date '+%Y-%m-%d %H:%M:%S'` Resizer finished round $ROUND." ) & sleep 2 echo echo "######################################################################" echo "#" echo "# `date '+%Y-%m-%d %H:%M:%S'` Waiting for completion of round $ROUND..." wait echo echo "######################################################################" echo "#" echo "# Stopping database server." "$MYSQLA" $PORT_1 $SOCK_1 -u root shutdown RC=$? sleep_until_pidfile_deleted "$PIDFILE" 60 echo if [ "`echo core*`" != "core*" ] then ls -l core* RC=1 fi if grep -Hi "corrupt|crash|incorrect key file" "$ERRFILE" \ || egrep -Hi "corrupt|crash|incorrect key file" bug17332-*.log then # Messages are printed by grep/egrep RC=1 fi if grep -H "ERROR" "$ERRFILE" \ || egrep -Hi "error" bug17332-*.log then # Messages are printed by grep/egrep : # RC=1 fi if [ "$RC" -ne 0 ] then break fi if [ -f "test_stop" ] then echo "Test stopped by existing file 'test_stop' after round $ROUND." break fi echo "Let the machine cool down after round $ROUND..." if [ -f "sleep_time" ] then sleep `cat sleep_time` else sleep $SLEEP_TIME fi echo echo ROUND=`expr $ROUND + 1` done echo "# End of Test." echo "#" echo "########################################################################"