fixed bugs in delayed insert replication and when slave loses connection after...

fixed bugs in delayed insert replication and when slave loses connection after Int_var but before Query
public test suite now tests replication code as well
parent f046a115
...@@ -5,38 +5,21 @@ ...@@ -5,38 +5,21 @@
# This scripts creates the privilege tables db, host, user, tables_priv, # This scripts creates the privilege tables db, host, user, tables_priv,
# columns_priv in the mysql database, as well as the func table. # columns_priv in the mysql database, as well as the func table.
ldata=var/lib
logdir=var/log
mdata=$ldata/mysql
execdir=../sql
bindir=../client
# Get mysqld/safe_mysqld options from /etc/my.cnf or ~/.my.cnf
if test -w /
then
conf=@sysconfdir@/my.cnf
else
conf=$HOME/.my.cnf
fi
if test -f "$conf" if [ x$1 = x"-slave" ]
then then
if grep "^datadir" $conf >/dev/null shift $#
then ldata=var/slave-data
ldata=`grep "^datadir" $conf | sed '.*=[ \t]*//` logdir=var/log
fi mdata=$ldata/mysql
if grep "^execdir" $conf >/dev/null execdir=../sql
then bindir=../client
execdir=`grep "^execdir" $conf | sed '.*=[ \t]*//` else
fi ldata=var/lib
if grep "^bindir" $conf >/dev/null logdir=var/log
then mdata=$ldata/mysql
bindir=`grep "^bindir" $conf | sed '.*=[ \t]*//` execdir=../sql
fi bindir=../client
if grep "^user" $conf >/dev/null
then
user=`grep "^user" $conf | sed '.*=[ \t]*//`
fi
fi fi
if test ! -x $execdir/mysqld if test ! -x $execdir/mysqld
...@@ -51,6 +34,7 @@ hostname=`hostname` # Install this too in the user table ...@@ -51,6 +34,7 @@ hostname=`hostname` # Install this too in the user table
resolved=127.0.0.1 resolved=127.0.0.1
# Create database directories mysql & test # Create database directories mysql & test
if test ! -d $ldata; then (mkdir -p $ldata || exit 1) && \ if test ! -d $ldata; then (mkdir -p $ldata || exit 1) && \
(chmod 700 $ldata || exit 1) ; fi (chmod 700 $ldata || exit 1) ; fi
...@@ -207,8 +191,8 @@ then ...@@ -207,8 +191,8 @@ then
c_c="$c_c comment='Column privileges';" c_c="$c_c comment='Column privileges';"
fi fi
if $execdir/mysqld --bootstrap --skip-grant-tables \ if $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \
--basedir=. --datadir=$ldata "$@" << END_OF_DATA --basedir=. --datadir=$ldata << END_OF_DATA
use mysql; use mysql;
$c_d $c_d
$i_d $i_d
......
...@@ -25,12 +25,18 @@ TOT_TEST=0 ...@@ -25,12 +25,18 @@ TOT_TEST=0
USERT=0 USERT=0
SYST=0 SYST=0
REALT=0 REALT=0
MY_TMP_DIR=$CWD/var/tmp
TIMEFILE="$CWD/var/tmp/mysqltest-time" TIMEFILE="$CWD/var/tmp/mysqltest-time"
DASHBLANK="---- ---- -------" DASHBLANK="---- ---- -------"
MYSQLD_SRC_DIRS="strings mysys include extra regex isam merge myisam \ MYSQLD_SRC_DIRS="strings mysys include extra regex isam merge myisam \
myisammrg heap sql" myisammrg heap sql"
GCOV_MSG=/tmp/mysqld-gcov.out #gcov output GCOV_MASTER_MSG=/tmp/mysqld-master-gcov.out #gcov output
GCOV_ERR=/tmp/mysqld-gcov.err GCOV_MASTER_ERR=/tmp/mysqld-master-gcov.err
GCOV_SLAVE_MSG=/tmp/mysqld-slave-gcov.out #gcov output
GCOV_SLAVE_ERR=/tmp/mysqld-slave-gcov.err
GCOV_SLAVE_SRC=/tmp/mysqld-slave-src/
[ -d $MY_TMP_DIR ] || mkdir -p $MY_TMP_DIR
[ -z $COLUMNS ] && COLUMNS=80 [ -z $COLUMNS ] && COLUMNS=80
E=`expr $COLUMNS - 8` E=`expr $COLUMNS - 8`
...@@ -45,12 +51,20 @@ done ...@@ -45,12 +51,20 @@ done
#++ #++
# mysqld Environment Parameters # mysqld Environment Parameters
#-- #--
MYPORT=9306 MYRUN_DIR=var/run
MYDDIR="$CWD/var/lib" MASTER_MYPORT=9306
MYSOCK="$CWD/var/tmp/mysql.sock" MASTER_MYDDIR="$CWD/var/lib"
MYPID="$CWD/var/run/mysqld.pid" MASTER_MYSOCK="$CWD/var/tmp/mysql.sock"
MYLOG="$CWD/var/log/mysqld.log" MASTER_MYPID="$CWD/var/run/mysqld.pid"
MYERR="$CWD/var/log/mysqld.err" MASTER_MYLOG="$CWD/var/log/mysqld.log"
MASTER_MYERR="$CWD/var/log/mysqld.err"
SLAVE_MYPORT=9307
SLAVE_MYDDIR="$CWD/var/slave-data"
SLAVE_MYSOCK="$CWD/var/tmp/mysql-slave.sock"
SLAVE_MYPID="$CWD/var/run/mysqld-slave.pid"
SLAVE_MYLOG="$CWD/var/log/mysqld-slave.log"
SLAVE_MYERR="$CWD/var/log/mysqld-slave.err"
#++ #++
# Program Definitions # Program Definitions
...@@ -70,7 +84,7 @@ XARGS=`which xargs` ...@@ -70,7 +84,7 @@ XARGS=`which xargs`
MYSQLD="$BASEDIR/sql/mysqld" MYSQLD="$BASEDIR/sql/mysqld"
MYSQL_TEST="$BASEDIR/client/mysqltest" MYSQL_TEST="$BASEDIR/client/mysqltest"
MYSQLADMIN="$BASEDIR/client/mysqladmin" MYSQLADMIN="$BASEDIR/client/mysqladmin"
MYSQL_TEST="$MYSQL_TEST --socket=$MYSOCK --database=$DB --user=$DBUSER --password=$DBPASSWD --silent" MYSQL_TEST="$MYSQL_TEST --socket=$MASTER_MYSOCK --database=$DB --user=$DBUSER --password=$DBPASSWD --silent"
INSTALL_DB="$MYBIN/mysql-test_install_db" INSTALL_DB="$MYBIN/mysql-test_install_db"
[ "$1" = "-gcov" ] && DO_GCOV=1 [ "$1" = "-gcov" ] && DO_GCOV=1
...@@ -165,52 +179,97 @@ report_stats () { ...@@ -165,52 +179,97 @@ report_stats () {
} }
mysql_install_db () { mysql_install_db () {
`$INSTALL_DB` $RM -rf $MASTER_MYDDIR $SLAVE_MYDDIR $SLAVE_MYLOG $MASTER_MYLOG \
$SLAVE_MYERR $MASTER_MYERR
[ -d $MYRUN_DIR ] || mkdir -p $MYRUN_DIR
$INSTALL_DB
if [ $? != 0 ]; then
error "Could not install master test DBs"
exit 1
fi
$INSTALL_DB -slave
if [ $? != 0 ]; then if [ $? != 0 ]; then
error "Could not install test DBs" error "Could not install slave test DBs"
exit 1 exit 1
fi fi
return 0 return 0
} }
gcov_clean () { gcov_prepare () {
$FIND $BASEDIR -name \*.gcov \ $FIND $BASEDIR -name \*.gcov \
-or -name \*.da | $XARGS $RM -or -name \*.da | $XARGS $RM
$RM -rf $GCOV_SLAVE_SRC
for d in $MYSQLD_SRC_DIRS; do
cd $BASEDIR/$d
mkdir -p $GCOV_SLAVE_SRC/$d
for f in *.h *.cc *.c; do
cp $f $GCOV_SLAVE_SRC/$d
done
cd $CWD
done
} }
gcov_collect () { gcov_collect () {
$ECHO "Collecting source coverage info..." $ECHO "Collecting source coverage info..."
[ -f $GCOV_MSG ] && $RM $GCOV_MSG [ -f $GCOV_MASTER_MSG ] && $RM $GCOV_MASTER_MSG
[ -f $GCOV_ERR ] && $RM $GCOV_ERR [ -f $GCOV_MASTER_ERR ] && $RM $GCOV_MASTER_ERR
[ -f $GCOV_SLAVE_MSG ] && $RM $GCOV_SLAVE_MSG
[ -f $GCOV_SLAVE_ERR ] && $RM $GCOV_SLAVE_ERR
for d in $MYSQLD_SRC_DIRS; do for d in $MYSQLD_SRC_DIRS; do
cd $BASEDIR/$d cd $BASEDIR/$d
for f in *.h *.cc *.c; do for f in *.h *.cc *.c; do
$GCOV $f 2>>$GCOV_ERR >>$GCOV_MSG $GCOV $f 2>>$GCOV_MASTER_ERR >>$GCOV_MASTER_MSG
done
cd $CWD
cd $GCOV_SLAVE_SRC/$d
for f in *.h *.cc *.c; do
$GCOV $f 2>>$GCOV_SLAVE_ERR >>$GCOV_SLAVE_MSG
done done
cd $CWD cd $CWD
done done
$ECHO "gcov info in $GCOV_MSG, errors in $GCOV_ERR" $ECHO "gcov master info in $GCOV_MASTER_MSG, errors in $GCOV_MASTER_ERR"
$ECHO "gcov slave info in $GCOV_SLAVE_MSG, errors in $GCOV_SLAVE_ERR"
} }
mysql_start () { mysql_start () {
cd $BASEDIR # for gcov cd $BASEDIR # for gcov
$MYSQLD --no-defaults \ #start master
--skip-networking \ $MYSQLD --no-defaults --log-bin \
--server-id=1 \
--basedir=$CWD \
--port=$MASTER_MYPORT \
--core-file \
--datadir=$MASTER_MYDDIR \
--pid-file=$MASTER_MYPID \
--socket=$MASTER_MYSOCK \
--log=$MASTER_MYLOG \
--language=english >> $MASTER_MYERR 2>&1 &
#allow master to get setteled so slave can connect right away without error
sleep 1
#start slave
$MYSQLD --no-defaults --server-id=2 \
--master-user=root \
--master-connect-retry=5 \
--master-host=127.0.0.1 \
--master-port=$MASTER_MYPORT \
--core-file \
--basedir=$CWD \ --basedir=$CWD \
--datadir=$MYDDIR \ --datadir=$SLAVE_MYDDIR \
--pid-file=$MYPID \ --pid-file=$SLAVE_MYPID \
--socket=$MYSOCK \ --port=$SLAVE_MYPORT \
--log=$MYLOG \ --socket=$SLAVE_MYSOCK \
--language=english >> $MYERR 2>&1 & --log=$SLAVE_MYLOG \
--language=english >> $SLAVE_MYERR 2>&1 &
cd $CWD cd $CWD
return 1 return 1
} }
mysql_stop () { mysql_stop () {
`$MYSQLADMIN --socket=$MYSOCK -u root shutdown` $MYSQLADMIN --socket=$MASTER_MYSOCK -u root shutdown
$MYSQLADMIN --socket=$SLAVE_MYSOCK -u root shutdown
return 1 return 1
} }
...@@ -230,13 +289,14 @@ mysql_restart () { ...@@ -230,13 +289,14 @@ mysql_restart () {
mysql_loadstd () { mysql_loadstd () {
sleep 2 #sleep 2
return 1 return 1
} }
[ "$DO_GCOV" -a ! -x "$GCOV" ] && error "No gcov found" [ "$DO_GCOV" -a ! -x "$GCOV" ] && error "No gcov found"
[ "$DO_GCOV" ] && gcov_clean # clean up stale gcov files if running with gcov [ "$DO_GCOV" ] && gcov_prepare
mysql_install_db mysql_install_db
...@@ -289,6 +349,9 @@ do ...@@ -289,6 +349,9 @@ do
total_inc total_inc
if [ $res != 0 ]; then if [ $res != 0 ]; then
$ECHO "failed output"
$CAT $TIMEFILE
$ECHO
$ECHO $ECHO
$SETCOLOR_NORMAL && $ECHO -n "Restarting mysqld $DASHBLANK" $SETCOLOR_NORMAL && $ECHO -n "Restarting mysqld $DASHBLANK"
mysql_restart mysql_restart
......
Table Op Msg_type Msg_text
test.words check status OK
name age id
Andy 31 00000001
Jacob 2 00000002
Caleb 1 00000003
unix_timestamp(t)
200006
This diff is collapsed.
source t/include/master-slave.inc;
connection master;
use test;
drop table if exists words;
create table words (word char(20) not null);
load data infile '../../std_data/words' into table words;
drop table if exists foo;
create table foo(n int);
insert into foo values(1),(2);
connection slave;
sleep 3;
use test;
@r/3.23/rpl000001.a.result select * from foo;
@r/3.23/rpl000001.b.result select sum(length(word)) from words;
source t/include/master-slave.inc;
connection master;
use test;
drop table if exists x;
create table x(n int auto_increment primary key);
set insert_id = 2000;
insert into x values (NULL),(NULL),(NULL);
connection slave;
use test;
sleep 1;
@r/3.23/rpl000002.result select * from x;
source t/include/master-slave.inc;
connection master;
drop table if exists x;
create table x(n int primary key);
!insert into x values (1),(2),(2);
insert into x values (3);
connection slave;
sleep 1;
@r/3.23/rpl000003.result select * from x;
source t/include/master-slave.inc;
connection master;
use test;
set SQL_LOG_BIN=0;
drop table if exists words;
create table words (word char(20) not null, index(word));
load data infile '../../std_data/words' into table words;
drop table if exists words1;
create table words1 (word char(20) not null);
load data infile '../../std_data/words' into table words1;
connection slave;
use test;
drop table if exists words;
load table words from master;
drop table if exists words1;
load table words1 from master;
@r/3.23/rpl000004.a.result check table words;
@r/3.23/rpl000004.b.result select count(*) from words1;
source t/include/master-slave.inc;
connection master;
drop table if exists test;
CREATE TABLE test (name varchar(64), age smallint(3));
INSERT INTO test SET name='Andy', age=31;
INSERT test SET name='Jacob', age=2;
INSERT into test SET name='Caleb', age=1;
ALTER TABLE test ADD id int(8) ZEROFILL AUTO_INCREMENT PRIMARY KEY;
@r/3.23/rpl000005.result select * from test;
connection slave;
sleep 1;
@r/3.23/rpl000005.result select * from test;
source t/include/master-slave.inc;
connection master;
set SQL_LOG_BIN=0;
set timestamp=200006;
drop table if exists foo;
create table foo(t timestamp not null,a char(1));
insert into foo ( a) values ('F');
@r/3.23/rpl000006.result select unix_timestamp(t) from foo;
connection slave;
drop table if exists foo;
load table foo from master;
@r/3.23/rpl000006.result select unix_timestamp(t) from foo;
connect (master,localhost,root,,test,0,var/tmp/mysql.sock);
connect (slave,localhost,root,,test,0,var/tmp/mysql-slave.sock);
connection slave;
!slave stop;
connection master;
reset master;
connection slave;
reset slave;
!slave start;
...@@ -1053,6 +1053,8 @@ static void safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) ...@@ -1053,6 +1053,8 @@ static void safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
static void safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) static void safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
{ {
mi->pending = 0; // if we lost connection after reading a state set event
// we will be re-reading it, so pending needs to be cleared
while(!slave_killed(thd) && mc_mysql_reconnect(mysql)) while(!slave_killed(thd) && mc_mysql_reconnect(mysql))
{ {
sql_print_error( sql_print_error(
......
...@@ -113,8 +113,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -113,8 +113,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
char *query=thd->query; char *query=thd->query;
DBUG_ENTER("mysql_insert"); DBUG_ENTER("mysql_insert");
/*
in safe mode or with skip-new change delayed insert to be regular
if we are told to replace duplicates, the insert cannot be concurrent
delayed insert changed to regular in slave thread
*/
if (lock_type == TL_WRITE_DELAYED && if (lock_type == TL_WRITE_DELAYED &&
(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) || ((specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) ||
thd->slave_thread
) ||
lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE) lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE)
lock_type=TL_WRITE; lock_type=TL_WRITE;
...@@ -1083,6 +1090,7 @@ bool delayed_insert::handle_inserts(void) ...@@ -1083,6 +1090,7 @@ bool delayed_insert::handle_inserts(void)
table->time_stamp=row->time_stamp; table->time_stamp=row->time_stamp;
info.handle_duplicates= row->dup; info.handle_duplicates= row->dup;
thd.net.last_errno = 0; // reset error for binlog
if (write_record(table,&info)) if (write_record(table,&info))
{ {
info.error++; // Ignore errors info.error++; // Ignore errors
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment