Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.1-new

into  mysql.com:/usr/local/home/marty/MySQL/mysql-5.1-new


sql/ha_ndbcluster.cc:
  Auto merged
sql/ha_ndbcluster.h:
  Auto merged
This commit is contained in:
unknown 2006-01-13 09:42:50 +01:00
commit a3748cda91
122 changed files with 8415 additions and 648 deletions

View file

@ -1670,3 +1670,8 @@ storage/ndb/test/ndbapi/testPartitioning
storage/ndb/test/ndbapi/testReadPerf
storage/ndb/test/ndbapi/test_event_merge
storage/ndb/test/tools/listen_event
libmysqld/ha_ndbcluster_binlog.cc
libmysqld/rpl_injector.cc
libmysqld/event.cc
libmysqld/event_executor.cc
libmysqld/event_timed.cc

View file

@ -852,10 +852,15 @@ static VAR *var_obtain(const char *name, int len)
return v;
}
/*
- if variable starts with a $ it is regarded as a local test varable
- if not it is treated as a environment variable, and the corresponding
environment variable will be updated
*/
int var_set(const char *var_name, const char *var_name_end,
const char *var_val, const char *var_val_end)
{
int digit;
int digit, result, env_var= 0;
VAR* v;
DBUG_ENTER("var_set");
DBUG_PRINT("enter", ("var_name: '%.*s' = '%.*s' (length: %d)",
@ -863,11 +868,11 @@ int var_set(const char *var_name, const char *var_name_end,
(int) (var_val_end - var_val), var_val,
(int) (var_val_end - var_val)));
if (*var_name++ != '$')
{
var_name--;
die("Variable name in %s does not start with '$'", var_name);
}
if (*var_name != '$')
env_var= 1;
else
var_name++;
digit = *var_name - '0';
if (!(digit < 10 && digit >= 0))
{
@ -875,7 +880,23 @@ int var_set(const char *var_name, const char *var_name_end,
}
else
v = var_reg + digit;
DBUG_RETURN(eval_expr(v, var_val, (const char**)&var_val_end));
result= eval_expr(v, var_val, (const char**) &var_val_end);
if (env_var)
{
char buf[1024];
memcpy(buf, v->name, v->name_len);
buf[v->name_len]= 0;
if (v->int_dirty)
{
sprintf(v->str_val, "%d", v->int_val);
v->int_dirty= 0;
v->str_val_len= strlen(v->str_val);
}
setenv(buf, v->str_val, 1);
}
DBUG_RETURN(result);
}
@ -1483,6 +1504,10 @@ int do_sync_with_master(struct st_query *query)
return do_sync_with_master2(offset);
}
/*
when ndb binlog is on, this call will wait until last updated epoch
(locally in the mysqld) has been received into the binlog
*/
int do_save_master_pos()
{
MYSQL_RES* res;
@ -1494,6 +1519,89 @@ int do_save_master_pos()
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
#ifdef HAVE_NDB_BINLOG
/*
Wait for ndb binlog to be up-to-date with all changes
done on the local mysql server
*/
{
ulong have_ndbcluster;
if (mysql_query(mysql, query= "show variables like 'have_ndbcluster'"))
die("At line %u: failed in %s: %d: %s", start_lineno, query,
mysql_errno(mysql), mysql_error(mysql));
if (!(res= mysql_store_result(mysql)))
die("line %u: mysql_store_result() retuned NULL for '%s'", start_lineno,
query);
if (!(row= mysql_fetch_row(res)))
die("line %u: empty result in %s", start_lineno, query);
have_ndbcluster= strcmp("YES", row[1]) == 0;
mysql_free_result(res);
if (have_ndbcluster)
{
ulonglong epoch, tmp_epoch= 0;
int count= 0;
do
{
const char binlog[]= "binlog";
const char latest_trans_epoch[]=
"latest_trans_epoch=";
const char latest_applied_binlog_epoch[]=
"latest_applied_binlog_epoch=";
if (count)
sleep(1);
if (mysql_query(mysql, query= "show engine ndb status"))
die("At line %u: failed in '%s': %d: %s", start_lineno, query,
mysql_errno(mysql), mysql_error(mysql));
if (!(res= mysql_store_result(mysql)))
die("line %u: mysql_store_result() retuned NULL for '%s'",
start_lineno, query);
while ((row= mysql_fetch_row(res)))
{
if (strcmp(row[1], binlog) == 0)
{
const char *status= row[2];
/* latest_trans_epoch */
if (count == 0)
{
while (*status && strncmp(status, latest_trans_epoch,
sizeof(latest_trans_epoch)-1))
status++;
if (*status)
{
status+= sizeof(latest_trans_epoch)-1;
epoch= strtoull(status, (char**) 0, 10);
}
else
die("line %u: result does not contain '%s' in '%s'",
start_lineno, latest_trans_epoch, query);
}
/* latest_applied_binlog_epoch */
while (*status && strncmp(status, latest_applied_binlog_epoch,
sizeof(latest_applied_binlog_epoch)-1))
status++;
if (*status)
{
status+= sizeof(latest_applied_binlog_epoch)-1;
tmp_epoch= strtoull(status, (char**) 0, 10);
}
else
die("line %u: result does not contain '%s' in '%s'",
start_lineno, latest_applied_binlog_epoch, query);
break;
}
}
mysql_free_result(res);
if (!row)
die("line %u: result does not contain '%s' in '%s'",
start_lineno, binlog, query);
count++;
} while (tmp_epoch < epoch && count <= 3);
}
}
#endif
if (mysql_query(mysql, query= "show master status"))
die("failed in show master status: %d: %s",
mysql_errno(mysql), mysql_error(mysql));
@ -1544,7 +1652,8 @@ int do_let(struct st_query *query)
while (*p && (*p != '=') && !my_isspace(charset_info,*p))
p++;
var_name_end= p;
if (var_name+1 == var_name_end)
if (var_name == var_name_end ||
(var_name+1 == var_name_end && *var_name == '$'))
die("Missing variable name in let");
while (my_isspace(charset_info,*p))
p++;

View file

@ -87,6 +87,11 @@ AC_DEFUN([MYSQL_CHECK_NDB_OPTIONS], [
[Extra CFLAGS for ndb compile]),
[ndb_ccflags=${withval}],
[ndb_ccflags=""])
AC_ARG_WITH([ndb-binlog],
[
--without-ndb-binlog Disable ndb binlog],
[ndb_binlog="$withval"],
[ndb_binlog="default"])
case "$ndb_ccflags" in
"yes")
@ -185,6 +190,7 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
ndbcluster_libs="\$(top_builddir)/storage/ndb/src/.libs/libndbclient.a"
ndbcluster_system_libs=""
ndb_mgmclient_libs="\$(top_builddir)/storage/ndb/src/mgmclient/libndbmgmclient.la"
mysql_se_objs="$mysql_se_objs ha_ndbcluster_binlog.o"
MYSQL_CHECK_NDB_OPTIONS
NDBCLUSTER_WORKAROUNDS
@ -219,6 +225,25 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
ndb_port="1186"
fi
have_ndb_binlog="no"
if test X"$ndb_binlog" = Xdefault ||
test X"$ndb_binlog" = Xyes
then
if test X"$have_row_based" = Xyes
then
have_ndb_binlog="yes"
fi
fi
if test X"$have_ndb_binlog" = Xyes
then
AC_DEFINE([HAVE_NDB_BINLOG], [1],
[Including Ndb Cluster Binlog])
AC_MSG_RESULT([Including Ndb Cluster Binlog])
else
AC_MSG_RESULT([Not including Ndb Cluster Binlog])
fi
ndb_transporter_opt_objs=""
if test "$ac_cv_func_shmget" = "yes" &&
test "$ac_cv_func_shmat" = "yes" &&

View file

@ -154,7 +154,14 @@ enum ha_extra_function {
to overwrite entire row.
*/
HA_EXTRA_KEYREAD_PRESERVE_FIELDS,
HA_EXTRA_MMAP
HA_EXTRA_MMAP,
/*
Ignore if the a tuple is not found, continue processing the
transaction and ignore that 'row'. Needed for idempotency
handling on the slave
*/
HA_EXTRA_IGNORE_NO_KEY,
HA_EXTRA_NO_IGNORE_NO_KEY
};
/* The following is parameter to ha_panic() */

View file

@ -49,7 +49,7 @@ enum enum_server_command
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE,
COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH,
COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON,
/* don't forget to update const char *command_name[] in sql_parse.cc */
/* Must be last */

View file

@ -66,11 +66,13 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
event_executor.cc event.cc event_timed.cc \
rpl_filter.cc sql_partition.cc handlerton.cc sql_plugin.cc \
sql_tablespace.cc
sql_tablespace.cc \
rpl_injector.cc
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
EXTRA_libmysqld_a_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \
ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
ha_ndbcluster_binlog.cc \
ha_partition.cc
libmysqld_a_DEPENDENCIES= @mysql_se_objs@
libmysqld_a_SOURCES=
@ -102,6 +104,9 @@ ha_berkeley.o: ha_berkeley.cc
ha_ndbcluster.o:ha_ndbcluster.cc
$(CXXCOMPILE) @ndbcluster_includes@ $(LM_CFLAGS) -c $<
ha_ndbcluster_binlog.o: ha_ndbcluster_binlog.cc
$(CXXCOMPILE) @ndbcluster_includes@ $(LM_CFLAGS) -c $<
# Until we can remove dependency on ha_ndbcluster.h
handler.o: handler.cc
$(CXXCOMPILE) @ndbcluster_includes@ $(LM_CFLAGS) -c $<

View file

@ -0,0 +1,2 @@
-- require r/have_ndb_extra.require
eval select $NDB_EXTRA_TEST;

View file

@ -0,0 +1,7 @@
-- require r/not_ndb.require
disable_query_log;
# so that both DISABLED and NO is output as NO
-- replace_result DISABLED NO
show variables like "have_ndbcluster";
enable_query_log;

View file

@ -594,3 +594,6 @@ CREATE TABLE event (
comment varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
PRIMARY KEY (db,name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
CREATE DATABASE IF NOT EXISTS cluster_replication;
CREATE TABLE IF NOT EXISTS cluster_replication.binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;

View file

@ -252,6 +252,16 @@ sub collect_one_test_case($$$$$$$) {
$tinfo->{'slave_restart'}= 1;
}
if ( ( $::opt_with_ndbcluster or $::glob_use_running_ndbcluster ) and
defined mtr_match_substring($tname,"ndb") )
{
$tinfo->{'ndb_test'}= 1;
}
else
{
$tinfo->{'ndb_test'}= 0;
}
# FIXME what about embedded_server + ndbcluster, skip ?!
my $master_opt_file= "$testdir/$tname-master.opt";

View file

@ -50,6 +50,23 @@ sub mtr_match_extension ($$) {
}
# Match a substring anywere in a string
sub mtr_match_substring ($$) {
my $string= shift;
my $substring= shift;
if ( $string =~ /(.*)\Q$substring\E(.*)$/ ) # strncmp
{
return $1;
}
else
{
return undef; # NULL
}
}
sub mtr_match_any_exact ($$) {
my $string= shift;
my $mlist= shift;

View file

@ -28,7 +28,7 @@ sub run_stress_test ()
if ( ! $::glob_use_embedded_server and ! $::opt_local_master )
{
$::master->[0]->{'pid'}= mysqld_start('master',0,[],[]);
$::master->[0]->{'pid'}= mysqld_start('master',0,[],[],0);
if ( ! $::master->[0]->{'pid'} )
{
mtr_error("Can't start the mysqld server");

View file

@ -140,9 +140,13 @@ our $glob_scriptname= undef;
our $glob_timers= undef;
our $glob_use_running_server= 0;
our $glob_use_running_ndbcluster= 0;
our $glob_use_running_ndbcluster_slave= 0;
our $glob_use_embedded_server= 0;
our @glob_test_mode;
our $using_ndbcluster_master= 0;
our $using_ndbcluster_slave= 0;
our $glob_basedir;
# The total result
@ -233,6 +237,8 @@ our $instance_manager;
our $opt_ndbcluster_port;
our $opt_ndbconnectstring;
our $opt_ndbcluster_port_slave;
our $opt_ndbconnectstring_slave;
our $opt_no_manager; # Does nothing now, we never use manager
our $opt_manager_port; # Does nothing now, we never use manager
@ -300,12 +306,16 @@ our $opt_udiff;
our $opt_skip_ndbcluster;
our $opt_with_ndbcluster;
our $opt_skip_ndbcluster_slave;
our $opt_with_ndbcluster_slave;
our $opt_ndb_extra_test;
our $exe_ndb_mgm;
our $path_ndb_tools_dir;
our $path_ndb_backup_dir;
our $file_ndb_testrun_log;
our $flag_ndb_status_ok= 1;
our $flag_ndb_slave_status_ok= 1;
######################################################################
#
@ -322,9 +332,13 @@ sub kill_running_server ();
sub kill_and_cleanup ();
sub check_ssl_support ();
sub check_ndbcluster_support ();
sub rm_ndbcluster_tables ($);
sub ndbcluster_install ();
sub ndbcluster_start ();
sub ndbcluster_start ($);
sub ndbcluster_stop ();
sub ndbcluster_install_slave ();
sub ndbcluster_start_slave ($);
sub ndbcluster_stop_slave ();
sub run_benchmarks ($);
sub run_tests ();
sub mysql_install_db ();
@ -333,8 +347,8 @@ sub run_testcase ($);
sub report_failure_and_restart ($);
sub do_before_start_master ($$);
sub do_before_start_slave ($$);
sub mysqld_start ($$$$);
sub mysqld_arguments ($$$$$);
sub mysqld_start ($$$$$);
sub mysqld_arguments ($$$$$$);
sub stop_masters_slaves ();
sub stop_masters ();
sub stop_slaves ();
@ -391,11 +405,11 @@ sub main () {
if ( $opt_start_dirty )
{
if ( ndbcluster_start() )
if ( ndbcluster_start($opt_with_ndbcluster) )
{
mtr_error("Can't start ndbcluster");
}
if ( mysqld_start('master',0,[],[]) )
if ( mysqld_start('master',0,[],[],$using_ndbcluster_master) )
{
mtr_report("Servers started, exiting");
}
@ -493,6 +507,7 @@ sub command_line_setup () {
my $opt_master_myport= 9306;
my $opt_slave_myport= 9308;
$opt_ndbcluster_port= 9350;
$opt_ndbcluster_port_slave= 9358;
my $im_port= 9310;
my $im_mysqld1_port= 9312;
my $im_mysqld2_port= 9314;
@ -529,6 +544,10 @@ sub command_line_setup () {
'force' => \$opt_force,
'with-ndbcluster' => \$opt_with_ndbcluster,
'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
'with-ndbcluster-slave' => \$opt_with_ndbcluster_slave,
'skip-ndbcluster-slave|skip-ndb-slave'
=> \$opt_skip_ndbcluster_slave,
'ndb-extra-test' => \$opt_ndb_extra_test,
'do-test=s' => \$opt_do_test,
'suite=s' => \$opt_suite,
'skip-rpl' => \$opt_skip_rpl,
@ -539,6 +558,7 @@ sub command_line_setup () {
'master_port=i' => \$opt_master_myport,
'slave_port=i' => \$opt_slave_myport,
'ndbcluster_port=i' => \$opt_ndbcluster_port,
'ndbcluster_port_slave=i' => \$opt_ndbcluster_port_slave,
'manager-port=i' => \$opt_manager_port, # Currently not used
'im-port=i' => \$im_port, # Instance Manager port.
'im-mysqld1-port=i' => \$im_mysqld1_port, # Port of mysqld, controlled by IM
@ -553,6 +573,7 @@ sub command_line_setup () {
# Run test on running server
'extern' => \$opt_extern,
'ndbconnectstring=s' => \$opt_ndbconnectstring,
'ndbconnectstring-slave=s' => \$opt_ndbconnectstring_slave,
# Debugging
'gdb' => \$opt_gdb,
@ -749,21 +770,6 @@ sub command_line_setup () {
}
}
if ( $opt_ndbconnectstring )
{
$glob_use_running_ndbcluster= 1;
$opt_with_ndbcluster= 1;
}
else
{
$opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port";
}
if ( $opt_skip_ndbcluster )
{
$opt_with_ndbcluster= 0;
}
# The ":s" in the argument spec, means we have three different cases
#
# undefined option not set
@ -855,6 +861,8 @@ sub command_line_setup () {
path_mysock => "$sockdir/slave.sock",
path_myport => $opt_slave_myport,
start_timeout => 400,
ndbcluster => 1, # ndbcluster not started
};
$slave->[1]=
@ -1188,6 +1196,8 @@ sub kill_running_server () {
ndbcluster_stop();
$master->[0]->{'ndbcluster'}= 1;
ndbcluster_stop_slave();
$slave->[0]->{'ndbcluster'}= 1;
}
}
@ -1285,13 +1295,9 @@ sub check_ndbcluster_support () {
if ($opt_skip_ndbcluster)
{
mtr_report("Skipping ndbcluster");
$opt_skip_ndbcluster_slave= 1;
$opt_with_ndbcluster= 0;
return;
}
if ($opt_with_ndbcluster)
{
mtr_report("Using ndbcluster");
$opt_with_ndbcluster_slave= 0;
return;
}
@ -1304,11 +1310,41 @@ sub check_ndbcluster_support () {
"", "/dev/null", "/dev/null", "") != 0 )
{
mtr_report("Skipping ndbcluster, mysqld not compiled with ndbcluster");
$opt_skip_ndbcluster= 1;
$opt_skip_ndbcluster_slave= 1;
$opt_with_ndbcluster= 0;
$opt_with_ndbcluster_slave= 0;
return;
}
mtr_report("Using ndbcluster, mysqld supports it");
$opt_with_ndbcluster= 1;
if ( $opt_ndbconnectstring )
{
$glob_use_running_ndbcluster= 1;
}
else
{
$opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port";
}
if ( $opt_skip_ndbcluster_slave )
{
$opt_with_ndbcluster_slave= 0;
}
else
{
$opt_with_ndbcluster_slave= 1;
if ( $opt_ndbconnectstring_slave )
{
$glob_use_running_ndbcluster_slave= 1;
}
else
{
$opt_ndbconnectstring_slave= "host=localhost:$opt_ndbcluster_port_slave";
}
}
return;
}
@ -1320,11 +1356,12 @@ sub ndbcluster_install () {
{
return 0;
}
mtr_report("Install ndbcluster");
mtr_report("Installing ndbcluster master");
my $ndbcluster_opts= $opt_bench ? "" : "--small";
if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port",
"--data-dir=$opt_vardir",
"--verbose=2",
$ndbcluster_opts,
"--initial"],
"", "", "", "") )
@ -1333,44 +1370,156 @@ sub ndbcluster_install () {
return 1;
}
$using_ndbcluster_master= 1;
ndbcluster_stop();
$master->[0]->{'ndbcluster'}= 1;
return 0;
}
sub ndbcluster_start () {
sub ndbcluster_start ($) {
my $use_ndbcluster= shift;
if ( ! $opt_with_ndbcluster or $glob_use_running_ndbcluster )
if ( ! $use_ndbcluster )
{
$using_ndbcluster_master= 0;
return 0;
}
if ( $glob_use_running_ndbcluster )
{
$using_ndbcluster_master= 1;
return 0;
}
if ( $using_ndbcluster_master )
{
return 0;
}
# FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
#mtr_report("Starting ndbcluster master");
if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port",
"--data-dir=$opt_vardir"],
"--data-dir=$opt_vardir",
"--verbose=2"],
"", "/dev/null", "", "") )
{
mtr_error("Error ndbcluster_start");
$using_ndbcluster_master= 0;
return 1;
}
$using_ndbcluster_master= 1;
return 0;
}
sub rm_ndbcluster_tables ($) {
my $dir= shift;
foreach my $bin ( glob("$dir/cluster_replication/apply_status*"),
glob("$dir/cluster_replication/schema*") )
{
unlink($bin);
}
}
sub ndbcluster_stop () {
if ( ! $opt_with_ndbcluster or $glob_use_running_ndbcluster )
if ( ! $using_ndbcluster_master or $glob_use_running_ndbcluster )
{
$using_ndbcluster_master= 0;
return;
}
# FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
#mtr_report("Stopping ndbcluster master");
mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port",
"--data-dir=$opt_vardir",
"--verbose=2",
"--stop"],
"", "/dev/null", "", "");
rm_ndbcluster_tables ($master->[0]->{'path_myddir'});
rm_ndbcluster_tables ($master->[1]->{'path_myddir'});
$using_ndbcluster_master= 0;
return;
}
sub ndbcluster_install_slave () {
if ( ! $opt_with_ndbcluster_slave or $glob_use_running_ndbcluster_slave )
{
return 0;
}
mtr_report("Installing ndbcluster slave");
if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port_slave",
"--data-dir=$opt_vardir",
"--verbose=2",
"--small",
"--ndbd-nodes=1",
"--initial"],
"", "", "", "") )
{
mtr_error("Error ndbcluster_install_slave");
return 1;
}
$using_ndbcluster_slave= 1;
ndbcluster_stop_slave();
$slave->[0]->{'ndbcluster'}= 1;
return 0;
}
sub ndbcluster_start_slave ($) {
my $use_ndbcluster= shift;
if ( ! $use_ndbcluster )
{
$using_ndbcluster_slave= 0;
return 0;
}
if ( $glob_use_running_ndbcluster_slave )
{
$using_ndbcluster_slave= 1;
return 0;
}
# FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
#mtr_report("Starting ndbcluster slave");
if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port_slave",
"--data-dir=$opt_vardir",
"--verbose=2",
"--ndbd-nodes=1"],
"", "/dev/null", "", "") )
{
mtr_error("Error ndbcluster_start_slave");
$using_ndbcluster_slave= 0;
return 1;
}
$using_ndbcluster_slave= 1;
return 0;
}
sub ndbcluster_stop_slave () {
if ( ! $using_ndbcluster_slave or $glob_use_running_ndbcluster_slave )
{
$using_ndbcluster_slave= 0;
return;
}
# FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
#mtr_report("Stopping ndbcluster slave");
mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
["--port=$opt_ndbcluster_port_slave",
"--data-dir=$opt_vardir",
"--verbose=2",
"--stop"],
"", "/dev/null", "", "");
rm_ndbcluster_tables ($slave->[0]->{'path_myddir'});
$using_ndbcluster_slave= 0;
return;
}
@ -1388,7 +1537,8 @@ sub run_benchmarks ($) {
if ( ! $glob_use_embedded_server and ! $opt_local_master )
{
$master->[0]->{'pid'}= mysqld_start('master',0,[],[]);
$master->[0]->{'pid'}= mysqld_start('master',0,[],[],
$using_ndbcluster_master);
if ( ! $master->[0]->{'pid'} )
{
mtr_error("Can't start the mysqld server");
@ -1525,6 +1675,13 @@ sub mysql_install_db () {
$flag_ndb_status_ok= 0;
}
if ( ndbcluster_install_slave() )
{
# failed to install, disable usage but flag that its no ok
$opt_with_ndbcluster_slave= 0;
$flag_ndb_slave_status_ok= 0;
}
return 0;
}
@ -1703,6 +1860,8 @@ sub run_testcase ($) {
my $tname= $tinfo->{'name'};
my $ndbcluster_opt;
mtr_tonewfile($opt_current_test,"$tname\n"); # Always tell where we are
# output current test to ndbcluster log file to enable diagnostics
@ -1736,7 +1895,8 @@ sub run_testcase ($) {
if ( ! $glob_use_running_server and ! $glob_use_embedded_server )
{
if ( $tinfo->{'master_restart'} or
$master->[0]->{'running_master_is_special'} )
$master->[0]->{'running_master_is_special'} or
( $tinfo->{'ndb_test'} != $using_ndbcluster_master ) )
{
stop_masters();
$master->[0]->{'running_master_is_special'}= 0; # Forget why we stopped
@ -1787,7 +1947,7 @@ sub run_testcase ($) {
{
if ( $master->[0]->{'ndbcluster'} )
{
$master->[0]->{'ndbcluster'}= ndbcluster_start();
$master->[0]->{'ndbcluster'}= ndbcluster_start($tinfo->{'ndb_test'});
if ( $master->[0]->{'ndbcluster'} )
{
report_failure_and_restart($tinfo);
@ -1799,17 +1959,19 @@ sub run_testcase ($) {
# FIXME not correct location for do_before_start_master()
do_before_start_master($tname,$tinfo->{'master_sh'});
$master->[0]->{'pid'}=
mysqld_start('master',0,$tinfo->{'master_opt'},[]);
mysqld_start('master',0,$tinfo->{'master_opt'},[],
$using_ndbcluster_master);
if ( ! $master->[0]->{'pid'} )
{
report_failure_and_restart($tinfo);
return;
}
}
if ( $opt_with_ndbcluster and ! $master->[1]->{'pid'} )
if ( $using_ndbcluster_master and ! $master->[1]->{'pid'} )
{
$master->[1]->{'pid'}=
mysqld_start('master',1,$tinfo->{'master_opt'},[]);
mysqld_start('master',1,$tinfo->{'master_opt'},[],
$using_ndbcluster_master);
if ( ! $master->[1]->{'pid'} )
{
report_failure_and_restart($tinfo);
@ -1848,9 +2010,25 @@ sub run_testcase ($) {
{
if ( ! $slave->[$idx]->{'pid'} )
{
$ndbcluster_opt= 0;
if ( $idx == 0)
{
if ( $slave->[0]->{'ndbcluster'} )
{
$slave->[0]->{'ndbcluster'}=
ndbcluster_start_slave($tinfo->{'ndb_test'});
if ( $slave->[0]->{'ndbcluster'} )
{
report_failure_and_restart($tinfo);
return;
}
}
$ndbcluster_opt= $using_ndbcluster_slave;
}
$slave->[$idx]->{'pid'}=
mysqld_start('slave',$idx,
$tinfo->{'slave_opt'}, $tinfo->{'slave_mi'});
$tinfo->{'slave_opt'}, $tinfo->{'slave_mi'},
$ndbcluster_opt);
if ( ! $slave->[$idx]->{'pid'} )
{
report_failure_and_restart($tinfo);
@ -2047,12 +2225,13 @@ sub do_before_start_slave ($$) {
}
}
sub mysqld_arguments ($$$$$) {
sub mysqld_arguments ($$$$$$) {
my $args= shift;
my $type= shift; # master/slave/bootstrap
my $idx= shift;
my $extra_opt= shift;
my $slave_master_info= shift;
my $using_ndbcluster= shift;
my $sidx= ""; # Index as string, 0 is empty string
if ( $idx > 0 )
@ -2115,6 +2294,12 @@ sub mysqld_arguments ($$$$$) {
{
mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
}
if ( $using_ndbcluster )
{
mtr_add_arg($args, "%s--ndbcluster", $prefix);
mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
$opt_ndbconnectstring);
}
}
if ( $type eq 'slave' )
@ -2171,6 +2356,17 @@ sub mysqld_arguments ($$$$$) {
mtr_add_arg($args, "%s--server-id=%d", $prefix, $slave_server_id);
mtr_add_arg($args, "%s--rpl-recovery-rank=%d", $prefix, $slave_rpl_rank);
}
if ( $opt_skip_ndbcluster_slave )
{
mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
}
if ( $idx == 0 and $using_ndbcluster_slave )
{
mtr_add_arg($args, "%s--ndbcluster", $prefix);
mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
$opt_ndbconnectstring_slave);
}
} # end slave
if ( $opt_debug )
@ -2187,13 +2383,6 @@ sub mysqld_arguments ($$$$$) {
}
}
if ( $opt_with_ndbcluster )
{
mtr_add_arg($args, "%s--ndbcluster", $prefix);
mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
$opt_ndbconnectstring);
}
# FIXME always set nowdays??? SMALL_SERVER
mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix);
mtr_add_arg($args, "%s--sort_buffer=256K", $prefix);
@ -2282,11 +2471,12 @@ sub mysqld_arguments ($$$$$) {
#
##############################################################################
sub mysqld_start ($$$$) {
sub mysqld_start ($$$$$) {
my $type= shift; # master/slave/bootstrap
my $idx= shift;
my $extra_opt= shift;
my $slave_master_info= shift;
my $using_ndbcluster= shift;
my $args; # Arg vector
my $exe;
@ -2312,7 +2502,8 @@ sub mysqld_start ($$$$) {
valgrind_arguments($args, \$exe);
}
mysqld_arguments($args,$type,$idx,$extra_opt,$slave_master_info);
mysqld_arguments($args,$type,$idx,$extra_opt,$slave_master_info,
$using_ndbcluster);
if ( $type eq 'master' )
{
@ -2408,6 +2599,12 @@ sub stop_slaves () {
}
}
if ( ! $slave->[0]->{'ndbcluster'} )
{
ndbcluster_stop_slave();
$slave->[0]->{'ndbcluster'}= 1;
}
mtr_stop_mysqld_servers(\@args);
}
@ -2617,6 +2814,8 @@ sub run_mysqltest ($) {
$ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults;
$ENV{'NDB_STATUS_OK'}= $flag_ndb_status_ok;
$ENV{'NDB_SLAVE_STATUS_OK'}= $flag_ndb_slave_status_ok;
$ENV{'NDB_EXTRA_TEST'}= $opt_ndb_extra_test;
$ENV{'NDB_MGM'}= $exe_ndb_mgm;
$ENV{'NDB_BACKUP_DIR'}= $path_ndb_backup_dir;
$ENV{'NDB_TOOLS_DIR'}= $path_ndb_tools_dir;
@ -2736,7 +2935,7 @@ sub run_mysqltest ($) {
if ( $glob_use_embedded_server )
{
mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[]);
mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[],0);
}
# ----------------------------------------------------------------------

View file

@ -222,11 +222,14 @@ export UMASK UMASK_DIR
MASTER_RUNNING=0
MASTER1_RUNNING=0
MASTER_MYHOST=127.0.0.1
MASTER_MYPORT=9306
SLAVE_RUNNING=0
SLAVE_MYHOST=127.0.0.1
SLAVE_MYPORT=9308 # leave room for 2 masters for cluster tests
MYSQL_MANAGER_PORT=9305 # needs to be out of the way of slaves
NDBCLUSTER_PORT=9350
NDBCLUSTER_PORT_SLAVE=9358
MYSQL_MANAGER_PW_FILE=$MYSQL_TEST_DIR/var/tmp/manager.pwd
MYSQL_MANAGER_LOG=$MYSQL_TEST_DIR/var/log/manager.log
MYSQL_MANAGER_USER=root
@ -262,7 +265,11 @@ EXTRA_MYSQLSHOW_OPT=""
EXTRA_MYSQLBINLOG_OPT=""
USE_RUNNING_SERVER=0
USE_NDBCLUSTER=@USE_NDBCLUSTER@
USE_NDBCLUSTER_SLAVE=@USE_NDBCLUSTER@
USE_RUNNING_NDBCLUSTER=""
USE_RUNNING_NDBCLUSTER_SLAVE=""
NDB_EXTRA_TEST=0
NDBCLUSTER_EXTRA_OPTS=""
USE_PURIFY=""
PURIFY_LOGS=""
DO_GCOV=""
@ -288,6 +295,7 @@ TEST_MODE=""
NDB_MGM_EXTRA_OPTS=
NDB_MGMD_EXTRA_OPTS=
NDBD_EXTRA_OPTS=
SLAVE_MYSQLDBINLOG=1
DO_STRESS=""
STRESS_SUITE="main"
@ -325,9 +333,18 @@ while test $# -gt 0; do
--extern) USE_RUNNING_SERVER=1 ;;
--with-ndbcluster)
USE_NDBCLUSTER="--ndbcluster" ;;
--with-ndbcluster-slave)
USE_NDBCLUSTER_SLAVE="--ndbcluster" ;;
--ndb-connectstring=*)
USE_NDBCLUSTER="--ndbcluster" ;
USE_RUNNING_NDBCLUSTER=`$ECHO "$1" | $SED -e "s;--ndb-connectstring=;;"` ;;
--ndb-connectstring-slave=*)
USE_NDBCLUSTER_SLAVE="--ndbcluster" ;
USE_RUNNING_NDBCLUSTER_SLAVE=`$ECHO "$1" | $SED -e "s;--ndb-connectstring-slave=;;"` ;;
--ndb-extra-test)
NDBCLUSTER_EXTRA_OPTS=" "
NDB_EXTRA_TEST=1 ;
;;
--ndb_mgm-extra-opts=*)
NDB_MGM_EXTRA_OPTS=`$ECHO "$1" | $SED -e "s;--ndb_mgm-extra-opts=;;"` ;;
--ndb_mgmd-extra-opts=*)
@ -344,6 +361,8 @@ while test $# -gt 0; do
--slave_port=*) SLAVE_MYPORT=`$ECHO "$1" | $SED -e "s;--slave_port=;;"` ;;
--manager-port=*) MYSQL_MANAGER_PORT=`$ECHO "$1" | $SED -e "s;--manager_port=;;"` ;;
--ndbcluster_port=*) NDBCLUSTER_PORT=`$ECHO "$1" | $SED -e "s;--ndbcluster_port=;;"` ;;
--ndbcluster-port=*) NDBCLUSTER_PORT=`$ECHO "$1" | $SED -e "s;--ndbcluster-port=;;"` ;;
--ndbcluster-port-slave=*) NDBCLUSTER_PORT_SLAVE=`$ECHO "$1" | $SED -e "s;--ndbcluster-port-slave=;;"` ;;
--with-openssl)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
--ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \
@ -500,6 +519,10 @@ while test $# -gt 0; do
TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"`
VALGRIND="$VALGRIND $TMP"
;;
--skip-ndbcluster-slave | --skip-ndb-slave)
USE_NDBCLUSTER_SLAVE=""
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-ndbcluster"
;;
--valgrind-mysqltest | --valgrind-mysqltest-all)
find_valgrind;
VALGRIND_MYSQLTEST=$FIND_VALGRIND
@ -510,9 +533,11 @@ while test $# -gt 0; do
;;
--skip-ndbcluster | --skip-ndb)
USE_NDBCLUSTER=""
USE_NDBCLUSTER_SLAVE=""
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-ndbcluster"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-ndbcluster"
;;
--skip-slave-binlog) SLAVE_MYSQLDBINLOG=0 ;;
--skip-*)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1"
@ -582,9 +607,13 @@ SLAVE_MYERR="$MYSQL_TEST_DIR/var/log/slave.err"
CURRENT_TEST="$MYSQL_TEST_DIR/var/log/current_test"
SMALL_SERVER="--key_buffer_size=1M --sort_buffer=256K --max_heap_table_size=1M"
export MASTER_MYPORT SLAVE_MYPORT MYSQL_TCP_PORT MASTER_MYSOCK MASTER_MYSOCK1
export MASTER_MYHOST MASTER_MYPORT SLAVE_MYHOST SLAVE_MYPORT MYSQL_TCP_PORT MASTER_MYSOCK MASTER_MYSOCK1
NDBCLUSTER_OPTS="--port=$NDBCLUSTER_PORT --data-dir=$MYSQL_TEST_DIR/var --ndb_mgm-extra-opts=$NDB_MGM_EXTRA_OPTS --ndb_mgmd-extra-opts=$NDB_MGMD_EXTRA_OPTS --ndbd-extra-opts=$NDBD_EXTRA_OPTS"
NDBCLUSTER_OPTS_SLAVE="--port=$NDBCLUSTER_PORT_SLAVE --data-dir=$MYSQL_TEST_DIR/var"
if [ -n "$USE_NDBCLUSTER_SLAVE" ] ; then
USE_NDBCLUSTER_SLAVE="$USE_NDBCLUSTER_SLAVE --ndb-connectstring=localhost:$NDBCLUSTER_PORT_SLAVE"
fi
NDB_BACKUP_DIR=$MYSQL_TEST_DIR/var/ndbcluster-$NDBCLUSTER_PORT
NDB_TOOLS_OUTPUT=$MYSQL_TEST_DIR/var/log/ndb_tools.log
@ -727,7 +756,6 @@ else
fi
MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
MYSQL_CHECK="$CLIENT_BINDIR/mysqlcheck"
MYSQL_DUMP="$CLIENT_BINDIR/mysqldump"
MYSQL_SLAP="$CLIENT_BINDIR/mysqlslap"
MYSQL_SHOW="$CLIENT_BINDIR/mysqlshow"
MYSQL_IMPORT="$CLIENT_BINDIR/mysqlimport"
@ -767,6 +795,13 @@ else
MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
MYSQL_CLIENT_TEST="$CLIENT_BINDIR/mysql_client_test"
fi
if [ -f "$BASEDIR/client/.libs/mysqldump" ] ; then
MYSQL_DUMP="$BASEDIR/client/.libs/mysqldump"
elif [ -f "$BASEDIR/client/mysqldump" ] ; then
MYSQL_DUMP="$BASEDIR/client/mysqldump"
else
MYSQL_DUMP="$BASEDIR/bin/mysqldump"
fi
fi
if [ -z "$MASTER_MYSQLD" ]
@ -829,6 +864,9 @@ export NDB_TOOLS_OUTPUT
export PURIFYOPTIONS
NDB_STATUS_OK=1
export NDB_STATUS_OK
NDB_SLAVE_STATUS_OK=1
export NDB_SLAVE_STATUS_OK
export NDB_EXTRA_TEST NDBCLUSTER_PORT NDBCLUSTER_PORT_SLAVE
MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB \
--user=$DBUSER --password=$DBPASSWD --silent -v --skip-safemalloc \
@ -1207,24 +1245,30 @@ EOF
start_ndbcluster()
{
if [ ! -z "$USE_NDBCLUSTER" ]
if [ ! -n "$USE_NDBCLUSTER" ] ;
then
USING_NDBCLUSTER=0
USE_NDBCLUSTER_OPT=
fi
if [ x$USING_NDBCLUSTER = x1 -a -z "$USE_NDBCLUSTER_OPT" ]
then
rm -f $NDB_TOOLS_OUTPUT
if [ -z "$USE_RUNNING_NDBCLUSTER" ]
then
echo "Starting ndbcluster"
if [ "$DO_BENCH" = 1 ]
if [ "$DO_BENCH" != 1 -a -z "$NDBCLUSTER_EXTRA_OPTS" ]
then
NDBCLUSTER_EXTRA_OPTS=""
else
NDBCLUSTER_EXTRA_OPTS="--small"
fi
./ndb/ndbcluster $NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --initial || NDB_STATUS_OK=0
OPTS="$NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --verbose=2 --initial"
echo "Starting master ndbcluster " $OPTS
./ndb/ndbcluster $OPTS || NDB_STATUS_OK=0
if [ x$NDB_STATUS_OK != x1 ] ; then
if [ x$FORCE != x1 ] ; then
exit 1
fi
USE_NDBCLUSTER=
USING_NDBCLUSTER=0
USE_NDBCLUSTER_OPT=
return
fi
@ -1233,19 +1277,30 @@ start_ndbcluster()
NDB_CONNECTSTRING="$USE_RUNNING_NDBCLUSTER"
echo "Using ndbcluster at $NDB_CONNECTSTRING"
fi
USE_NDBCLUSTER="$USE_NDBCLUSTER --ndb-connectstring=\"$NDB_CONNECTSTRING\""
USE_NDBCLUSTER_OPT="$USE_NDBCLUSTER --ndb-connectstring=\"$NDB_CONNECTSTRING\""
export NDB_CONNECTSTRING
fi
}
rm_ndbcluster_tables()
{
$RM -f $1/cluster_replication/apply_status*
$RM -f $1/cluster_replication/schema*
}
stop_ndbcluster()
{
if [ ! -z "$USE_NDBCLUSTER" ]
if [ -n "$USE_NDBCLUSTER_OPT" ]
then
USE_NDBCLUSTER_OPT=
if [ -z "$USE_RUNNING_NDBCLUSTER" ]
then
# Kill any running ndbcluster stuff
$ECHO "Stopping master cluster"
./ndb/ndbcluster $NDBCLUSTER_OPTS --stop
# remove ndb table the hard way as not to upset later tests
rm_ndbcluster_tables $MASTER_MYDDIR
rm_ndbcluster_tables $MASTER_MYDDIR"1"
fi
fi
}
@ -1300,7 +1355,7 @@ start_master()
--local-infile \
--exit-info=256 \
--core \
$USE_NDBCLUSTER \
$USE_NDBCLUSTER_OPT \
--datadir=$MASTER_MYDDIR$1 \
--pid-file=$MASTER_MYPID$1 \
--socket=$MASTER_MYSOCK$1 \
@ -1330,7 +1385,7 @@ start_master()
--character-sets-dir=$CHARSETSDIR \
--default-character-set=$CHARACTER_SET \
--core \
$USE_NDBCLUSTER \
$USE_NDBCLUSTER_OPT \
--tmpdir=$MYSQL_TMP_DIR \
--language=$LANGUAGE \
--innodb_data_file_path=ibdata1:128M:autoextend \
@ -1397,6 +1452,7 @@ start_slave()
[ x$SKIP_SLAVE = x1 ] && return
eval "this_slave_running=\$SLAVE$1_RUNNING"
[ x$this_slave_running = 1 ] && return
# When testing fail-safe replication, we will have more than one slave
# in this case, we start secondary slaves with an argument
slave_ident="slave$1"
@ -1420,6 +1476,36 @@ start_slave()
slave_pid=$SLAVE_MYPID
slave_sock="$SLAVE_MYSOCK"
fi
#
if [ x$USING_NDBCLUSTER = x1 -a -n "$USE_NDBCLUSTER_SLAVE" ] ; then
if [ $slave_server_id -eq 2 ] ; then
savedir=`pwd`
cd $MYSQL_TEST_DIR
if [ "$DO_BENCH" != 1 -a -z "$NDBCLUSTER_EXTRA_OPTS" ]
then
NDBCLUSTER_EXTRA_OPTS="--small"
fi
OPTS="$NDBCLUSTER_OPTS_SLAVE --initial $NDBCLUSTER_EXTRA_OPTS --ndbd-nodes=1 --verbose=2"
echo "Starting slave ndbcluster " $OPTS
./ndb/ndbcluster $OPTS \
|| NDB_SLAVE_STATUS_OK=0
# > /dev/null 2>&1 || NDB_SLAVE_STATUS_OK=0
cd $savedir
if [ x$NDB_SLAVE_STATUS_OK != x1 ] ; then
if [ x$FORCE != x1 ] ; then
exit 1
fi
USE_NDBCLUSTER_SLAVE_OPT=
USE_NDBCLUSTER_SLAVE=
fi
USE_NDBCLUSTER_SLAVE_OPT=$USE_NDBCLUSTER_SLAVE
fi
else
USE_NDBCLUSTER_SLAVE_OPT=
fi
# Remove stale binary logs and old master.info files
# except for too tests which need them
if [ "$tname" != "rpl_crash_binlog_ib_1b" ] && [ "$tname" != "rpl_crash_binlog_ib_2b" ] && [ "$tname" != "rpl_crash_binlog_ib_3b" ]
@ -1445,12 +1531,16 @@ start_slave()
master_info=$SLAVE_MASTER_INFO
fi
if [ x$SLAVE_MYSQLDBINLOG = x1 ]
then
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --log-bin=$MYSQL_TEST_DIR/var/log/$slave_ident-bin --log-slave-updates"
fi
$RM -f $slave_datadir/log.*
slave_args="--no-defaults $master_info \
--exit-info=256 \
--log-bin=$MYSQL_TEST_DIR/var/log/$slave_ident-bin \
$SLAVE_MYSQLDBINLOG_OPT \
--relay-log=$MYSQL_TEST_DIR/var/log/$slave_ident-relay-bin \
--log-slave-updates \
--log=$slave_log \
--basedir=$MY_BASEDIR \
--datadir=$slave_datadir \
@ -1472,7 +1562,8 @@ start_slave()
--log-bin-trust-function-creators \
--loose-binlog-show-xid=0 \
$SMALL_SERVER \
$EXTRA_SLAVE_MYSQLD_OPT $EXTRA_SLAVE_OPT"
$EXTRA_SLAVE_MYSQLD_OPT $EXTRA_SLAVE_OPT \
$USE_NDBCLUSTER_SLAVE_OPT"
CUR_MYERR=$slave_err
CUR_MYSOCK=$slave_sock
@ -1520,7 +1611,6 @@ mysql_start ()
# start_master
# start_slave
cd $MYSQL_TEST_DIR
start_ndbcluster
return 1
}
@ -1554,6 +1644,14 @@ stop_slave ()
sleep $SLEEP_TIME_AFTER_RESTART
fi
eval "SLAVE$1_RUNNING=0"
if [ -n "$USE_NDBCLUSTER_SLAVE_OPT" ] ; then
savedir=`pwd`
cd $MYSQL_TEST_DIR
$ECHO "Stopping slave cluster"
./ndb/ndbcluster $NDBCLUSTER_OPTS_SLAVE --stop
rm_ndbcluster_tables $SLAVE_MYDDIR
cd $savedir
fi
fi
}
@ -1642,6 +1740,7 @@ run_testcase ()
result_file="r/$tname.result"
echo $tname > $CURRENT_TEST
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0 \& \( $tname : federated \) = 0`
NDBCLUSTER_TEST=`$EXPR \( $tname : '.*ndb.*' \) != 0`
if [ "$USE_MANAGER" = 1 ] ; then
many_slaves=`$EXPR \( \( $tname : rpl_failsafe \) != 0 \) \| \( \( $tname : rpl_chain_temp_table \) != 0 \)`
fi
@ -1731,9 +1830,19 @@ run_testcase ()
esac
stop_master
stop_master 1
# only stop the cluster if this test will not use cluster
if [ x$NDBCLUSTER_TEST != x1 ] ;
then
stop_ndbcluster
fi
report_current_test $tname
USING_NDBCLUSTER=$NDBCLUSTER_TEST
# start_ndbcluster knows if cluster is already started
start_ndbcluster
start_master
if [ -n "$USE_NDBCLUSTER" -a -z "$DO_BENCH" -a -z "$DO_STRESS" ] ; then
if [ x$USING_NDBCLUSTER = x1 -a -z "$DO_BENCH" -a -z "$DO_STRESS" ] ; then
start_master 1
fi
TZ=$MY_TZ; export TZ
@ -1742,14 +1851,25 @@ run_testcase ()
# or there is no master running (FIXME strange.....)
# or there is a master init script
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || \
[ -f $master_init_script ]
[ -f $master_init_script ] || \
[ -n "$USE_NDBCLUSTER" -a x$NDBCLUSTER_TEST != x$USING_NDBCLUSTER ]
then
EXTRA_MASTER_OPT=""
stop_master
stop_master 1
# only stop the cluster if this test will not use cluster
if [ x$NDBCLUSTER_TEST != x1 ] ;
then
stop_ndbcluster
fi
report_current_test $tname
USING_NDBCLUSTER=$NDBCLUSTER_TEST
# start_ndbcluster knows if cluster is already started
start_ndbcluster
start_master
if [ -n "$USE_NDBCLUSTER" -a -z "$DO_BENCH" -a -z "$DO_STRESS" ] ; then
if [ x$USING_NDBCLUSTER = x1 -a -z "$DO_BENCH" -a -z "$DO_STRESS" ] ; then
start_master 1
fi
else
@ -1783,6 +1903,18 @@ run_testcase ()
fi
fi
USING_NDBCLUSTER=$NDBCLUSTER_TEST
if [ -n "$USE_NDBCLUSTER_SLAVE_OPT" ] ; then
if [ x$USING_NDBCLUSTER != x1 ] ; then
do_slave_restart=1
fi
else
if [ x$USING_NDBCLUSTER = x1 ] ; then
do_slave_restart=1
fi
fi
if [ x$do_slave_restart = x1 ] ; then
stop_slave
echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
@ -2041,6 +2173,8 @@ then
fi
fi
# just to force stopping anything from previous runs
USE_NDBCLUSTER_OPT=$USE_NDBCLUSTER
stop_ndbcluster
# Remove files that can cause problems
@ -2058,7 +2192,8 @@ then
if [ -n "$1" -a `expr "X$*" : '.*ndb'` -eq 0 ]
then
USE_NDBCLUSTER=""
USING_NDBCLUSTER=0
USE_NDBCLUSTER_OPT=
fi
start_manager
@ -2090,7 +2225,7 @@ then
EXTRA_BENCH_ARGS="--small-test --small-tables"
fi
if [ ! -z "$USE_NDBCLUSTER" ]
if [ x$USING_NDBCLUSTER = x1 ]
then
EXTRA_BENCH_ARGS="--create-options=TYPE=ndb $EXTRA_BENCH_ARGS"
fi

View file

@ -6,7 +6,7 @@ test_SCRIPTS = ndbcluster
noinst_HEADERS = ndbcluster.sh
dist_test_DATA = ndb_config_2_node.ini
dist_test_DATA = ndb_config_2_node.ini ndb_config_1_node.ini
SUFFIXES = .sh

View file

@ -12433,31 +12433,108 @@ a b
DROP TABLE t5;
CREATE TABLE `t5` (
`a` int(11) NOT NULL auto_increment,
b char(12),
b blob(12),
KEY (`a`)
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (32, "foo");
INSERT INTO t5 VALUES (23, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (3, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "We the people");
INSERT INTO t5 VALUES (NULL, "in order to form a more pefect union");
INSERT INTO t5 VALUES (NULL, "establish justice");
INSERT INTO t5 VALUES (NULL, "foo grok ");
INSERT INTO t5 VALUES (32, "ensure domestic tranquility");
INSERT INTO t5 VALUES (23, "provide for the common defense");
INSERT INTO t5 VALUES (NULL, "fo fooo");
INSERT INTO t5 VALUES (NULL, "foo just naother bit of text");
INSERT INTO t5 VALUES (3, "foo this is mine to think about");
INSERT INTO t5 VALUES (NULL, "promote the general welfare");
SELECT * FROM t5;
a b
1 foo
2 foo
3 foo
4 foo
5 foo
32 foo
23 foo
33 foo
34 foo
3 foo
35 foo
2 We the people
3 in order to form a more pefect union
4 establish justice
5 foo grok
32 ensure domestic tranquility
23 provide for the common defense
33 fo fooo
34 foo just naother bit of text
3 foo this is mine to think about
35 promote the general welfare
SELECT b FROM t5;
b
foo
We the people
in order to form a more pefect union
establish justice
foo grok
ensure domestic tranquility
provide for the common defense
fo fooo
foo just naother bit of text
foo this is mine to think about
promote the general welfare
SELECT b FROM t5 WHERE a =3;
b
in order to form a more pefect union
foo this is mine to think about
SELECT b FROM t5 WHERE a IN (32, 23, 5);
b
foo grok
ensure domestic tranquility
provide for the common defense
DROP TABLE t5;
CREATE TABLE `t5` (
`a` int(11) NOT NULL auto_increment,
b blob(12),
c blob(12),
KEY (`a`)
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
INSERT INTO t5 VALUES (NULL, "foo", "grok this!");
INSERT INTO t5 VALUES (NULL, "We the people", NULL);
INSERT INTO t5 VALUES (NULL, "in order to form a more peefect union", "secure the blessing of liberty");
INSERT INTO t5 VALUES (NULL, "establish justice", "to ourselves and");
INSERT INTO t5 VALUES (32, "ensure domestic tranquility", NULL);
INSERT INTO t5 VALUES (23, "provide for the common defense", "posterity");
INSERT INTO t5 VALUES (NULL, "promote the general welfare", "do ordain");
SELECT * FROM t5;
a b c
1 foo grok this!
2 We the people NULL
3 in order to form a more peefect union secure the blessing of liberty
4 establish justice to ourselves and
32 ensure domestic tranquility NULL
23 provide for the common defense posterity
33 promote the general welfare do ordain
SELECT b FROM t5;
b
foo
We the people
in order to form a more peefect union
establish justice
ensure domestic tranquility
provide for the common defense
promote the general welfare
SELECT b FROM t5 WHERE a =3;
b
in order to form a more peefect union
SELECT b FROM t5 WHERE a IN (32, 23, 5);
b
ensure domestic tranquility
provide for the common defense
SELECT c FROM t5;
c
grok this!
NULL
secure the blessing of liberty
to ourselves and
NULL
posterity
do ordain
SELECT c FROM t5 WHERE a =3;
c
secure the blessing of liberty
SELECT c FROM t5 WHERE a IN (32, 23, 5);
c
NULL
posterity
drop table t1, t2, t4, t5;

View file

@ -47,6 +47,7 @@ create database mysqltest;
show databases;
Database
information_schema
cluster_replication
mysql
mysqltest
test
@ -58,6 +59,7 @@ drop database mysqltest;
show databases;
Database
information_schema
cluster_replication
mysql
test
drop database mysqltest;

View file

@ -0,0 +1,3 @@
select 1;
1
1

View file

@ -14,6 +14,7 @@ NULL test latin1 latin1_swedish_ci NULL
select schema_name from information_schema.schemata;
schema_name
information_schema
cluster_replication
mysql
test
show databases like 't%';
@ -22,6 +23,7 @@ test
show databases;
Database
information_schema
cluster_replication
mysql
test
show databases where `database` = 't%';
@ -55,6 +57,7 @@ TABLE_PRIVILEGES
TRIGGERS
VIEWS
USER_PRIVILEGES
binlog_index
columns_priv
db
event
@ -331,6 +334,7 @@ create view v0 (c) as select schema_name from information_schema.schemata;
select * from v0;
c
information_schema
cluster_replication
mysql
test
explain select * from v0;
@ -728,7 +732,7 @@ CREATE TABLE t_crashme ( f1 BIGINT);
CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
count(*)
106
107
drop view a2, a1;
drop table t_crashme;
select table_schema,table_name, column_name from
@ -810,6 +814,7 @@ delete from mysql.db where user='mysqltest_4';
flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
table_schema count(*)
cluster_replication 1
information_schema 19
mysql 19
create table t1 (i int, j int);

View file

@ -1,3 +1,4 @@
cluster_replication.binlog_index OK
mysql.columns_priv OK
mysql.db OK
mysql.event OK

View file

@ -215,12 +215,11 @@ a long $where variable content
mysqltest: At line 1: Missing arguments to let
mysqltest: At line 1: Missing variable name in let
mysqltest: At line 1: Variable name in hi=hi does not start with '$'
mysqltest: At line 1: Missing assignment operator in let
mysqltest: At line 1: Missing assignment operator in let
mysqltest: At line 1: Missing arguments to let
mysqltest: At line 1: Missing variable name in let
mysqltest: At line 1: Variable name in =hi does not start with '$'
mysqltest: At line 1: Missing variable name in let
mysqltest: At line 1: Missing assignment operator in let
mysqltest: At line 1: Missing file name in source
mysqltest: At line 1: Could not open file ./non_existingFile

View file

@ -170,35 +170,6 @@ c
4
5
drop table t1;
create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
engine=ndb;
insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
create index c on t1(c);
select * from t1 where b = 'two';
a b c
2 two two
alter table t1 drop index c;
select * from t1 where b = 'two';
ERROR HY000: Can't lock file (errno: 159)
select * from t1 where b = 'two';
a b c
2 two two
drop table t1;
create table t3 (a int primary key) engine=ndbcluster;
begin;
insert into t3 values (1);
alter table t3 rename t4;
delete from t3;
insert into t3 values (1);
commit;
select * from t3;
ERROR HY000: Can't lock file (errno: 155)
select * from t4;
a
1
drop table t4;
show tables;
Tables_in_test
create table t1 (
ai bigint auto_increment,
c001 int(11) not null,

View file

@ -0,0 +1,26 @@
DROP TABLE IF EXISTS t1;
create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
engine=ndb;
insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
create index c on t1(c);
select * from t1 where c = 'two';
a b c
2 two two
alter table t1 drop index c;
select * from t1 where c = 'two';
a b c
2 two two
drop table t1;
create table t3 (a int primary key) engine=ndbcluster;
begin;
insert into t3 values (1);
alter table t3 rename t4;
commit;
select * from t3;
ERROR 42S02: Table 'test.t3' doesn't exist
select * from t4;
a
1
drop table t4;
show tables;
Tables_in_test

View file

@ -0,0 +1,30 @@
DROP TABLE IF EXISTS t1;
create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
engine=ndb;
insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
create index c on t1(c);
select * from t1 where c = 'two';
a b c
2 two two
alter table t1 drop index c;
select * from t1 where c = 'two';
ERROR HY000: Can't lock file (errno: 159)
select * from t1 where c = 'two';
a b c
2 two two
drop table t1;
create table t3 (a int primary key) engine=ndbcluster;
begin;
insert into t3 values (1);
alter table t3 rename t4;
delete from t3;
insert into t3 values (1);
commit;
select * from t3;
ERROR HY000: Can't lock file (errno: 155)
select * from t4;
a
1
drop table t4;
show tables;
Tables_in_test

View file

@ -6,6 +6,13 @@ attr1 INT NOT NULL,
attr2 INT,
attr3 VARCHAR(10)
) ENGINE=ndbcluster;
drop table t1;
CREATE TABLE t1 (
pk1 INT NOT NULL PRIMARY KEY,
attr1 INT NOT NULL,
attr2 INT,
attr3 VARCHAR(10)
) ENGINE=ndbcluster;
SHOW INDEX FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 pk1 A 0 NULL NULL BTREE

View file

@ -0,0 +1,62 @@
drop table if exists t1, t2;
drop database if exists mysqltest;
create database mysqltest;
use mysqltest;
drop database mysqltest;
use test;
create table t1 (a int primary key) engine=ndb;
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
select @max_epoch:=max(epoch)-1 from cluster_replication.binlog_index;
@max_epoch:=max(epoch)-1
#
delete from t1;
alter table t1 add (b int);
insert into t1 values (3,3),(4,4);
alter table t1 rename t2;
begin;
insert into t2 values (1,1),(2,2);
update t2 set b=1 where a=3;
delete from t2 where a=4;
commit;
drop table t2;
select inserts from cluster_replication.binlog_index where epoch > @max_epoch and inserts > 5;
inserts
10
select deletes from cluster_replication.binlog_index where epoch > @max_epoch and deletes > 5;
deletes
10
select inserts,updates,deletes from
cluster_replication.binlog_index where epoch > @max_epoch and updates > 0;
inserts updates deletes
2 1 1
select schemaops from
cluster_replication.binlog_index where epoch > @max_epoch and schemaops > 0;
schemaops
1
1
1
flush logs;
purge master logs before now();
select count(*) from cluster_replication.binlog_index;
count(*)
0
create table t1 (a int primary key, b int) engine=ndb;
create database mysqltest;
use mysqltest;
create table t1 (c int, d int primary key) engine=ndb;
use test;
insert into mysqltest.t1 values (2,1),(2,2);
select @max_epoch:=max(epoch)-1 from cluster_replication.binlog_index;
@max_epoch:=max(epoch)-1
#
drop table t1;
drop database mysqltest;
select inserts,updates,deletes from
cluster_replication.binlog_index where epoch > @max_epoch and inserts > 0;
inserts updates deletes
2 0 0
select schemaops from
cluster_replication.binlog_index where epoch > @max_epoch and schemaops > 0;
schemaops
1
1

View file

@ -0,0 +1,43 @@
drop table if exists t1,t2;
drop table if exists t1,t2;
SHOW TABLES;
Tables_in_test
CREATE TABLE t2 (a INT PRIMARY KEY, b int) ENGINE = NDB;
show tables;
Tables_in_test
t2
INSERT INTO t2 VALUES (1,1),(2,2);
select * from t2 order by a;
a b
1 1
2 2
SELECT @the_epoch:=epoch,inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index ORDER BY epoch DESC LIMIT 1;
@the_epoch:=epoch inserts updates deletes schemaops
<the_epoch> 2 0 0 0
SELECT * FROM t2 ORDER BY a;
a b
1 1
2 2
SELECT inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index WHERE epoch=<the_epoch>;
inserts updates deletes schemaops
2 0 0 0
DROP TABLE t2;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE = NDB;
INSERT INTO t1 VALUES (1),(2);
SELECT @the_epoch2:=epoch,inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index ORDER BY epoch DESC LIMIT 1;
@the_epoch2:=epoch inserts updates deletes schemaops
<the_epoch2> 2 0 0 0
SELECT inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index WHERE epoch > <the_epoch> AND epoch < <the_epoch2>;
inserts updates deletes schemaops
0 0 0 1
drop table t1;
SHOW TABLES;
Tables_in_test
SELECT inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index WHERE epoch > <the_epoch> AND epoch < <the_epoch2>;
inserts updates deletes schemaops
0 0 0 1

View file

@ -1,4 +1,5 @@
drop table if exists t1, t2, t3, t4;
drop table if exists t1, t2, t3, t4;
flush status;
create table t1 (a int) engine=ndbcluster;
create table t2 (a int) engine=ndbcluster;

View file

@ -0,0 +1,69 @@
drop table if exists t1, t2, t3, t4;
drop table if exists t1, t2, t3, t4;
flush status;
create table t1 (a int) engine=ndbcluster;
create table t2 (a int) engine=ndbcluster;
insert into t1 value (2);
insert into t2 value (3);
select * from t1;
a
2
select * from t2;
a
3
show status like 'handler_discover%';
Variable_name Value
Handler_discover 0
select * from t1;
a
2
drop table t1;
create table t1 (a int) engine=ndbcluster;
insert into t1 value (2);
select * from t1;
a
2
show status like 'handler_discover%';
Variable_name Value
Handler_discover 0
drop table t1;
create table t1 (a int) engine=ndbcluster;
insert into t1 value (2);
select * from t1;
a
2
flush status;
select * from t1;
a
2
update t1 set a=3 where a=2;
show status like 'handler_discover%';
Variable_name Value
Handler_discover 0
create table t3 (a int not null primary key, b varchar(22),
c int, last_col text) engine=ndb;
insert into t3 values(1, 'Hi!', 89, 'Longtext column');
create table t4 (pk int primary key, b int) engine=ndb;
select * from t1;
a
3
select * from t3;
a b c last_col
1 Hi! 89 Longtext column
show status like 'handler_discover%';
Variable_name Value
Handler_discover 1
show tables like 't4';
Tables_in_test (t4)
t4
show status like 'handler_discover%';
Variable_name Value
Handler_discover 2
show tables;
Tables_in_test
t1
t2
t3
t4
drop table t1, t2, t3, t4;
drop table t1, t3, t4;

View file

@ -0,0 +1,2 @@
Variable_name Value
have_ndbcluster NO

View file

@ -259,6 +259,7 @@ prepare stmt4 from ' show databases ';
execute stmt4;
Database
information_schema
cluster_replication
mysql
test
prepare stmt4 from ' show tables from test like ''t2%'' ';

View file

@ -33,6 +33,7 @@ create database mysqltest;
show databases;
Database
information_schema
cluster_replication
mysql
mysqltest
mysqltest2
@ -50,6 +51,7 @@ set sql_log_bin = 1;
show databases;
Database
information_schema
cluster_replication
mysql
test
create database mysqltest2;
@ -69,6 +71,7 @@ load data from master;
show databases;
Database
information_schema
cluster_replication
mysql
mysqltest
mysqltest2

View file

@ -23,6 +23,7 @@ ALTER DATABASE mysqltest_bob CHARACTER SET latin1;
SHOW DATABASES;
Database
information_schema
cluster_replication
mysql
mysqltest_bob
mysqltest_prometheus
@ -31,6 +32,7 @@ test
SHOW DATABASES;
Database
information_schema
cluster_replication
mysql
mysqltest_prometheus
mysqltest_sisyfos
@ -45,6 +47,7 @@ CREATE TABLE t2 (a INT);
SHOW DATABASES;
Database
information_schema
cluster_replication
mysql
mysqltest_bob
mysqltest_prometheus
@ -53,6 +56,7 @@ test
SHOW DATABASES;
Database
information_schema
cluster_replication
mysql
mysqltest_prometheus
mysqltest_sisyfos

View file

@ -21,6 +21,7 @@ COUNT(*)
SHOW DATABASES;
Database
information_schema
cluster_replication
mysql
mysqltest
test

View file

@ -0,0 +1,120 @@
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;
CREATE DATABASE IF NOT EXISTS BANK;
DROP DATABASE BANK;
CREATE DATABASE BANK default charset=latin1 default collate=latin1_bin;
USE BANK;
CREATE TABLE GL ( TIME BIGINT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
BALANCE INT UNSIGNED NOT NULL,
DEPOSIT_COUNT INT UNSIGNED NOT NULL,
DEPOSIT_SUM INT UNSIGNED NOT NULL,
WITHDRAWAL_COUNT INT UNSIGNED NOT NULL,
WITHDRAWAL_SUM INT UNSIGNED NOT NULL,
PURGED INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (TIME,ACCOUNT_TYPE))
ENGINE = NDB;
CREATE TABLE ACCOUNT ( ACCOUNT_ID INT UNSIGNED NOT NULL,
OWNER INT UNSIGNED NOT NULL,
BALANCE INT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (ACCOUNT_ID))
ENGINE = NDB;
CREATE TABLE TRANSACTION ( TRANSACTION_ID BIGINT UNSIGNED NOT NULL,
ACCOUNT INT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
OTHER_ACCOUNT INT UNSIGNED NOT NULL,
TRANSACTION_TYPE INT UNSIGNED NOT NULL,
TIME BIGINT UNSIGNED NOT NULL,
AMOUNT INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (TRANSACTION_ID,ACCOUNT))
ENGINE = NDB;
CREATE TABLE SYSTEM_VALUES ( SYSTEM_VALUES_ID INT UNSIGNED NOT NULL,
VALUE BIGINT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (SYSTEM_VALUES_ID))
ENGINE = NDB;
CREATE TABLE ACCOUNT_TYPE ( ACCOUNT_TYPE_ID INT UNSIGNED NOT NULL,
DESCRIPTION CHAR(64) NOT NULL,
PRIMARY KEY USING HASH (ACCOUNT_TYPE_ID))
ENGINE = NDB;
STOP SLAVE;
RESET SLAVE;
CREATE DATABASE IF NOT EXISTS BANK;
DROP DATABASE BANK;
CREATE DATABASE BANK;
RESET MASTER;
CREATE TABLE IF NOT EXISTS cluster_replication.backup_info (id INT, backup_id INT) ENGINE = HEAP;
DELETE FROM cluster_replication.backup_info;
LOAD DATA INFILE '../../var/tmp.dat' INTO TABLE cluster_replication.backup_info FIELDS TERMINATED BY ',';
SELECT @the_backup_id:=backup_id FROM cluster_replication.backup_info;
@the_backup_id:=backup_id
<the_backup_id>
SELECT @the_epoch:=MAX(epoch) FROM cluster_replication.apply_status;
@the_epoch:=MAX(epoch)
<the_epoch>
SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
FROM cluster_replication.binlog_index WHERE epoch > <the_epoch> ORDER BY epoch ASC LIMIT 1;
@the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1)
<the_pos> master-bin.000001
CHANGE MASTER TO
master_log_file = 'master-bin.000001',
master_log_pos = <the_pos>;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
START SLAVE;
use test;
create table t1 (a int primary key) engine=ndb;
insert into t1 values (1);
drop table t1;

View file

@ -0,0 +1,90 @@
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;
CREATE TABLE `t1` ( `nid` int(11) NOT NULL default '0',
`nom` char(4) default NULL,
`prenom` char(4) default NULL,
PRIMARY KEY (`nid`))
ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES(1,"XYZ1","ABC1");
select * from t1 order by nid;
nid nom prenom
1 XYZ1 ABC1
select * from t1 order by nid;
nid nom prenom
1 XYZ1 ABC1
delete from t1;
INSERT INTO t1 VALUES(1,"XYZ2","ABC2");
select * from t1 order by nid;
nid nom prenom
1 XYZ2 ABC2
select * from t1 order by nid;
nid nom prenom
1 XYZ2 ABC2
DROP table t1;
CREATE TABLE `t1` ( `nid` int(11) NOT NULL default '0',
`nom` char(4) default NULL,
`prenom` char(4) default NULL)
ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES(1,"XYZ1","ABC1"),(2,"AAA","BBB"),(3,"CCC","DDD");
select * from t1 order by nid;
nid nom prenom
1 XYZ1 ABC1
2 AAA BBB
3 CCC DDD
select * from t1 order by nid;
nid nom prenom
1 XYZ1 ABC1
2 AAA BBB
3 CCC DDD
delete from t1 where nid = 2;
INSERT INTO t1 VALUES(4,"EEE","FFF");
select * from t1 order by nid;
nid nom prenom
1 XYZ1 ABC1
3 CCC DDD
4 EEE FFF
select * from t1 order by nid;
nid nom prenom
1 XYZ1 ABC1
3 CCC DDD
4 EEE FFF
UPDATE t1 set nid=nid+1;
UPDATE t1 set nom="CCP" where nid = 4;
select * from t1 order by nid;
nid nom prenom
2 XYZ1 ABC1
4 CCP DDD
5 EEE FFF
select * from t1 order by nid;
nid nom prenom
2 XYZ1 ABC1
4 CCP DDD
5 EEE FFF
DROP table t1;
CREATE TABLE `t1` ( `nid` int(11) NOT NULL default '0',
`nom` char(4) default NULL,
`prenom` char(4) default NULL,
PRIMARY KEY USING HASH (`nid`))
ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES(1,"XYZ1","ABC1");
BEGIN;
UPDATE t1 SET `nom`="LOCK" WHERE `nid`=1;
set GLOBAL slave_transaction_retries=1;
UPDATE t1 SET `nom`="DEAD" WHERE `nid`=1;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes No <Replicate_Ignore_Table> 146 Error in Write_rows event: error during transaction execution on table test.t1 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
set GLOBAL slave_transaction_retries=10;
START SLAVE;
select * from t1 order by nid;
nid nom prenom
1 LOCK ABC1
COMMIT;
select * from t1 order by nid;
nid nom prenom
1 DEAD ABC1
DROP TABLE t1;

View file

@ -0,0 +1,73 @@
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;
DROP TABLE IF EXISTS t1;
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
UNDO_BUFFER_SIZE = 1M
ENGINE=NDB;
alter logfile group lg1
add undofile 'undofile02.dat'
initial_size 4M engine=ndb;
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
INITIAL_SIZE 12M
ENGINE NDB;
alter tablespace ts1
add datafile 'datafile02.dat'
initial_size 4M engine=ndb;
CREATE TABLE t1
(pk1 int not null primary key, b int not null, c int not null)
tablespace ts1 storage disk
engine ndb;
insert into t1 values (1,2,3);
select * from t1 order by pk1;
pk1 b c
1 2 3
select * from t1 order by pk1;
pk1 b c
1 2 3
show binlog events;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 4 Format_desc 1 102 Server ver: VERSION, Binlog ver: 4
master-bin.000001 102 Query 1 188 use `test`; DROP TABLE IF EXISTS t1
master-bin.000001 188 Query 1 353 CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
UNDO_BUFFER_SIZE = 1M
ENGINE=NDB
master-bin.000001 353 Query 1 496 alter logfile group lg1
add undofile 'undofile02.dat'
initial_size 4M engine=ndb
master-bin.000001 496 Query 1 658 CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
INITIAL_SIZE 12M
ENGINE NDB
master-bin.000001 658 Query 1 798 alter tablespace ts1
add datafile 'datafile02.dat'
initial_size 4M engine=ndb
master-bin.000001 798 Query 1 978 use `test`; CREATE TABLE t1
(pk1 int not null primary key, b int not null, c int not null)
tablespace ts1 storage disk
engine ndb
master-bin.000001 978 Query 1 1042 BEGIN
master-bin.000001 1042 Table_map 1 65 cluster_replication.apply_status
master-bin.000001 1107 Write_rows 1 107
master-bin.000001 1149 Table_map 1 148 test.t1
master-bin.000001 1190 Write_rows 1 190
master-bin.000001 1232 Query 1 1297 COMMIT
drop table t1;
alter tablespace ts1
drop datafile 'datafile.dat'
engine=ndb;
alter tablespace ts1
drop datafile 'datafile02.dat'
engine=ndb;
DROP TABLESPACE ts1 ENGINE=NDB;
DROP LOGFILE GROUP lg1 ENGINE=NDB;

View file

@ -0,0 +1,72 @@
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;
CREATE TABLE t1 (c1 CHAR(15), c2 CHAR(15), c3 INT, PRIMARY KEY (c3)) ENGINE = NDB ;
INSERT INTO t1 VALUES ("row1","will go away",1);
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row1 will go away 1
SELECT @the_epoch:=MAX(epoch) FROM cluster_replication.apply_status;
@the_epoch:=MAX(epoch)
<the_epoch>
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row1 will go away 1
SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
FROM cluster_replication.binlog_index WHERE epoch = <the_epoch> ;
@the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1)
<the_pos> master-bin.000001
INSERT INTO t1 VALUES ("row2","will go away",2),("row3","will change",3),("row4","D",4);
DELETE FROM t1 WHERE c3 = 1;
UPDATE t1 SET c2="should go away" WHERE c3 = 2;
UPDATE t1 SET c2="C" WHERE c3 = 3;
DELETE FROM t1 WHERE c3 = 2;
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row3 C 3
row4 D 4
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row3 C 3
row4 D 4
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
STOP SLAVE;
CHANGE MASTER TO
master_log_file = 'master-bin.000001',
master_log_pos = <the_pos> ;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 No No <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
START SLAVE;
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row3 C 3
row4 D 4
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row3 C 3
row4 D 4
STOP SLAVE;
DROP TABLE t1;
RESET master;
DROP TABLE t1;
RESET slave;
START SLAVE;
CREATE TABLE t1 (c1 CHAR(15) NOT NULL, c2 CHAR(15) NOT NULL, c3 INT NOT NULL, PRIMARY KEY (c3)) ENGINE = NDB ;
INSERT INTO t1 VALUES ("row1","remove on slave",1);
DELETE FROM t1;
BEGIN;
UPDATE t1 SET c2="does not exist" WHERE c3=1;
INSERT INTO t1 VALUES ("row2","new on slave",2);
COMMIT;
SELECT * FROM t1;
c1 c2 c3
row2 new on slave 2
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>

View file

@ -0,0 +1,42 @@
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;
DROP DATABASE IF EXISTS TEST_DB;
CREATE DATABASE TEST_DB;
USE TEST_DB;
CREATE TABLE SUBSCRIBER
( NUMBER CHAR(12) BINARY NOT NULL,
NAME CHAR(32) BINARY NOT NULL,
GROUP_ID INT UNSIGNED NOT NULL,
LOCATION INT UNSIGNED NOT NULL,
SESSIONS INT UNSIGNED NOT NULL,
CHANGED_BY CHAR(32) BINARY NOT NULL,
CHANGED_TIME CHAR(32) BINARY NOT NULL,
PRIMARY KEY USING HASH (NUMBER))
ENGINE = NDB;
CREATE TABLE GROUP2
( GROUP_ID INT UNSIGNED NOT NULL,
GROUP_NAME CHAR(32) BINARY NOT NULL,
ALLOW_READ CHAR(1) BINARY NOT NULL,
ALLOW_INSERT INT UNSIGNED NOT NULL,
ALLOW_DELETE INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (GROUP_ID))
ENGINE = NDB;
CREATE TABLE SESSION
( NUMBER CHAR(12) BINARY NOT NULL,
SERVER_ID INT UNSIGNED NOT NULL,
DATA BINARY(2000) NOT NULL,
PRIMARY KEY USING HASH (NUMBER,SERVER_ID))
ENGINE = NDB;
CREATE TABLE SERVER
( SUFFIX CHAR(2) BINARY NOT NULL,
SERVER_ID INT UNSIGNED NOT NULL,
NAME CHAR(32) BINARY NOT NULL,
NO_OF_READ INT UNSIGNED NOT NULL,
NO_OF_INSERT INT UNSIGNED NOT NULL,
NO_OF_DELETE INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (SUFFIX, SERVER_ID))
ENGINE = NDB;

View file

@ -0,0 +1,55 @@
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;
CREATE TABLE t1 (c1 CHAR(15), c2 CHAR(15), c3 INT, PRIMARY KEY (c3)) ENGINE = NDB ;
reset master;
SHOW TABLES;
Tables_in_test
t1
INSERT INTO t1 VALUES ("row1","will go away",1);
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row1 will go away 1
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row1 will go away 1
SELECT @the_epoch:=MAX(epoch) FROM cluster_replication.apply_status;
@the_epoch:=MAX(epoch)
<the_epoch>
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row1 will go away 1
stop slave;
SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
FROM cluster_replication.binlog_index WHERE epoch = <the_epoch> ;
@the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1)
102 master-bin1.000001
CHANGE MASTER TO
master_port=<MASTER_PORT1>,
master_log_file = 'master-bin1.000001',
master_log_pos = 102 ;
start slave;
INSERT INTO t1 VALUES ("row2","will go away",2),("row3","will change",3),("row4","D",4);
DELETE FROM t1 WHERE c3 = 1;
UPDATE t1 SET c2="should go away" WHERE c3 = 2;
UPDATE t1 SET c2="C" WHERE c3 = 3;
DELETE FROM t1 WHERE c3 = 2;
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row3 C 3
row4 D 4
INSERT INTO t1 VALUES ("row5","E",5);
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row3 C 3
row4 D 4
row5 E 5
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row3 C 3
row4 D 4
row5 E 5
STOP SLAVE;

View file

@ -0,0 +1,95 @@
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;
STOP SLAVE;
CREATE DATABASE ndbsynctest;
USE ndbsynctest;
CREATE DATABASE ndbsynctest;
USE ndbsynctest;
CREATE TABLE t1 (c1 BIT(1) NOT NULL, c2 BIT(1) NOT NULL, c3 CHAR(15), PRIMARY KEY(c3)) ENGINE = NDB ;
INSERT INTO t1 VALUES (1,1,"row1"),(0,1,"row2"),(1,0,"row3"),(0,0,"row4");
CREATE TABLE t2 (c1 CHAR(15), c2 BIT(1) NOT NULL, c3 BIT(1) NOT NULL, PRIMARY KEY(c1)) ENGINE = NDB ;
INSERT INTO t2 VALUES ("ABC",1,1),("BCDEF",0,1),("CD",1,0),("DEFGHIJKL",0,0);
SELECT hex(c1),hex(c2),c3 FROM t1 ORDER BY c3;
hex(c1) hex(c2) c3
1 1 row1
0 1 row2
1 0 row3
0 0 row4
SELECT hex(c2),hex(c3),c1 FROM t2 ORDER BY c1;
hex(c2) hex(c3) c1
1 1 ABC
0 1 BCDEF
1 0 CD
0 0 DEFGHIJKL
CREATE TABLE IF NOT EXISTS cluster_replication.backup_info (id INT, backup_id INT);
DELETE FROM cluster_replication.backup_info;
LOAD DATA INFILE '../../var/tmp.dat' INTO TABLE cluster_replication.backup_info FIELDS TERMINATED BY ',';
SELECT @the_backup_id:=backup_id FROM cluster_replication.backup_info;
@the_backup_id:=backup_id
<the_backup_id>
UPDATE t1 SET c2=0 WHERE c3="row2";
SELECT hex(c1),hex(c2),c3 FROM t1 ORDER BY c3;
hex(c1) hex(c2) c3
1 1 row1
0 0 row2
1 0 row3
0 0 row4
SHOW TABLES;
Tables_in_ndbsynctest
DROP DATABASE ndbsynctest;
CREATE DATABASE ndbsynctest;
USE ndbsynctest;
SHOW TABLES;
Tables_in_ndbsynctest
t1
t2
SELECT hex(c1),hex(c2),c3 FROM t1 ORDER BY c3;
hex(c1) hex(c2) c3
1 1 row1
0 1 row2
1 0 row3
0 0 row4
SELECT hex(c2),hex(c3),c1 FROM t2 ORDER BY c1;
hex(c2) hex(c3) c1
1 1 ABC
0 1 BCDEF
1 0 CD
0 0 DEFGHIJKL
SELECT @the_epoch:=MAX(epoch) FROM cluster_replication.apply_status;
@the_epoch:=MAX(epoch)
<the_epoch>
SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
FROM cluster_replication.binlog_index WHERE epoch > <the_epoch> ORDER BY epoch ASC LIMIT 1;
@the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1)
<the_pos> master-bin.000001
CHANGE MASTER TO
master_log_file = 'master-bin.000001',
master_log_pos = <the_pos> ;
START SLAVE;
SHOW SLAVE STATUS;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
<Slave_IO_State> 127.0.0.1 root MASTER_PORT 1 master-bin.000001 <Read_Master_Log_Pos> <Relay_Log_File> <Relay_Log_Pos> master-bin.000001 Yes Yes <Replicate_Ignore_Table> 0 0 <Exec_Master_Log_Pos> <Relay_Log_Space> None 0 No <Seconds_Behind_Master>
SELECT hex(c1),hex(c2),c3 FROM t1 ORDER BY c3;
hex(c1) hex(c2) c3
1 1 row1
0 0 row2
1 0 row3
0 0 row4
SELECT hex(c2),hex(c3),c1 FROM t2 ORDER BY c1;
hex(c2) hex(c3) c1
1 1 ABC
0 1 BCDEF
1 0 CD
0 0 DEFGHIJKL
DROP DATABASE ndbsynctest;
STOP SLAVE;
reset master;
select * from cluster_replication.binlog_index;
Position File epoch inserts updates deletes schemaops
reset slave;
select * from cluster_replication.apply_status;
server_id epoch

View file

@ -9,6 +9,7 @@ CREATE DATABASE test_ignore;
SHOW DATABASES;
Database
information_schema
cluster_replication
mysql
test
test_ignore
@ -33,6 +34,7 @@ master-bin.000001 235 Write_rows 1 282
SHOW DATABASES;
Database
information_schema
cluster_replication
mysql
test
USE test;

View file

@ -0,0 +1,426 @@
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;
CREATE TABLE t1 (C1 CHAR(1), C2 CHAR(1), INDEX (C1)) ENGINE = 'NDB' ;
SELECT * FROM t1;
C1 C2
SELECT * FROM t1;
C1 C2
INSERT INTO t1 VALUES ('A','B'), ('X','Y'), ('X','X');
INSERT INTO t1 VALUES ('A','C'), ('X','Z'), ('A','A');
SELECT * FROM t1 ORDER BY C1,C2;
C1 C2
A A
A B
A C
X X
X Y
X Z
SELECT * FROM t1 ORDER BY C1,C2;
C1 C2
A A
A B
A C
X X
X Y
X Z
DELETE FROM t1 WHERE C1 = C2;
SELECT * FROM t1 ORDER BY C1,C2;
C1 C2
A B
A C
X Y
X Z
SELECT * FROM t1 ORDER BY C1,C2;
C1 C2
A B
A C
X Y
X Z
UPDATE t1 SET C2 = 'I' WHERE C1 = 'A' AND C2 = 'C';
SELECT * FROM t1 ORDER BY C1,C2;
C1 C2
A B
A I
X Y
X Z
SELECT * FROM t1 ORDER BY C1,C2;
C1 C2
A B
A I
X Y
X Z
UPDATE t1 SET c2 = 'Q' WHERE c1 = 'A' AND c2 = 'N';
SELECT * FROM t1 ORDER BY c1,c2;
C1 C2
A B
A I
X Y
X Z
SELECT * FROM t1 ORDER BY c1,c2;
C1 C2
A B
A I
X Y
X Z
CREATE TABLE t2 (c1 INT, c12 char(1), c2 INT, PRIMARY KEY (c1)) ENGINE = 'NDB' ;
INSERT INTO t2
VALUES (1,'A',2), (2,'A',4), (3,'A',9), (4,'A',15), (5,'A',25),
(6,'A',35), (7,'A',50), (8,'A',64), (9,'A',81);
SELECT * FROM t2 ORDER BY c1,c2;
c1 c12 c2
1 A 2
2 A 4
3 A 9
4 A 15
5 A 25
6 A 35
7 A 50
8 A 64
9 A 81
SELECT * FROM t2 WHERE c2 = c1 * c1 ORDER BY c1,c2;
c1 c12 c2
2 A 4
3 A 9
5 A 25
8 A 64
9 A 81
SELECT * FROM t2 ORDER BY c1,c2;
c1 c12 c2
1 A 2
2 A 4
3 A 9
4 A 15
5 A 25
6 A 35
7 A 50
8 A 64
9 A 81
SELECT * FROM t2 WHERE c2 = c1 * c1 ORDER BY c1,c2;
c1 c12 c2
2 A 4
3 A 9
5 A 25
8 A 64
9 A 81
UPDATE t2 SET c2 = c1*c1 WHERE c2 != c1*c1;
SELECT * FROM t2 WHERE c2 = c1 * c1 ORDER BY c1,c2;
c1 c12 c2
1 A 1
2 A 4
3 A 9
4 A 16
5 A 25
6 A 36
7 A 49
8 A 64
9 A 81
SELECT * FROM t2 WHERE c2 = c1 * c1 ORDER BY c1,c2;
c1 c12 c2
1 A 1
2 A 4
3 A 9
4 A 16
5 A 25
6 A 36
7 A 49
8 A 64
9 A 81
UPDATE t2 SET c12 = 'Q' WHERE c1 = 1 AND c2 = 999;
SELECT * FROM t2 ORDER BY c1,c2;
c1 c12 c2
1 A 1
2 A 4
3 A 9
4 A 16
5 A 25
6 A 36
7 A 49
8 A 64
9 A 81
SELECT * FROM t2 ORDER BY c1,c2;
c1 c12 c2
1 A 1
2 A 4
3 A 9
4 A 16
5 A 25
6 A 36
7 A 49
8 A 64
9 A 81
DELETE FROM t2 WHERE c1 % 4 = 0;
SELECT * FROM t2 ORDER BY c1,c2;
c1 c12 c2
1 A 1
2 A 4
3 A 9
5 A 25
6 A 36
7 A 49
9 A 81
SELECT * FROM t2 ORDER BY c1,c2;
c1 c12 c2
1 A 1
2 A 4
3 A 9
5 A 25
6 A 36
7 A 49
9 A 81
UPDATE t2 SET c12='X';
CREATE TABLE t3 (C1 CHAR(1), C2 CHAR(1), pk1 INT, C3 CHAR(1), pk2 INT, PRIMARY KEY (pk1,pk2)) ENGINE = 'NDB' ;
INSERT INTO t3 VALUES ('A','B',1,'B',1), ('X','Y',2,'B',1), ('X','X',3,'B',1);
INSERT INTO t3 VALUES ('A','C',1,'B',2), ('X','Z',2,'B',2), ('A','A',3,'B',2);
SELECT * FROM t3 ORDER BY C1,C2;
C1 C2 pk1 C3 pk2
A A 3 B 2
A B 1 B 1
A C 1 B 2
X X 3 B 1
X Y 2 B 1
X Z 2 B 2
SELECT * FROM t3 ORDER BY C1,C2;
C1 C2 pk1 C3 pk2
A A 3 B 2
A B 1 B 1
A C 1 B 2
X X 3 B 1
X Y 2 B 1
X Z 2 B 2
DELETE FROM t3 WHERE C1 = C2;
SELECT * FROM t3 ORDER BY C1,C2;
C1 C2 pk1 C3 pk2
A B 1 B 1
A C 1 B 2
X Y 2 B 1
X Z 2 B 2
SELECT * FROM t3 ORDER BY C1,C2;
C1 C2 pk1 C3 pk2
A B 1 B 1
A C 1 B 2
X Y 2 B 1
X Z 2 B 2
UPDATE t3 SET C2 = 'I' WHERE C1 = 'A' AND C2 = 'C';
SELECT * FROM t3 ORDER BY C1,C2;
C1 C2 pk1 C3 pk2
A B 1 B 1
A I 1 B 2
X Y 2 B 1
X Z 2 B 2
SELECT * FROM t3 ORDER BY C1,C2;
C1 C2 pk1 C3 pk2
A B 1 B 1
A I 1 B 2
X Y 2 B 1
X Z 2 B 2
CREATE TABLE t6 (C1 CHAR(1), C2 CHAR(1), C3 INT) ENGINE = 'NDB' ;
INSERT INTO t6 VALUES ('A','B',1), ('X','Y',2), ('X','X',3);
INSERT INTO t6 VALUES ('A','C',4), ('X','Z',5), ('A','A',6);
SELECT * FROM t6 ORDER BY C3;
C1 C2 C3
A B 1
X Y 2
X X 3
A C 4
X Z 5
A A 6
SELECT * FROM t6 ORDER BY C3;
C1 C2 C3
A B 1
X Y 2
X X 3
A C 4
X Z 5
A A 6
DELETE FROM t6 WHERE C1 = C2;
SELECT * FROM t6 ORDER BY C3;
C1 C2 C3
A B 1
X Y 2
A C 4
X Z 5
SELECT * FROM t6 ORDER BY C3;
C1 C2 C3
A B 1
X Y 2
A C 4
X Z 5
UPDATE t6 SET C2 = 'I' WHERE C1 = 'A' AND C2 = 'C';
SELECT * FROM t6 ORDER BY C3;
C1 C2 C3
A B 1
X Y 2
A I 4
X Z 5
SELECT * FROM t6 ORDER BY C3;
C1 C2 C3
A B 1
X Y 2
A I 4
X Z 5
CREATE TABLE t5 (C1 CHAR(1), C2 CHAR(1), C3 INT PRIMARY KEY) ENGINE = 'NDB' ;
INSERT INTO t5 VALUES ('A','B',1), ('X','Y',2), ('X','X',3);
INSERT INTO t5 VALUES ('A','C',4), ('X','Z',5), ('A','A',6);
UPDATE t5,t2,t3 SET t5.C2='Q', t2.c12='R', t3.C3 ='S' WHERE t5.C1 = t2.c12 AND t5.C1 = t3.C1;
SELECT * FROM t5,t2,t3 WHERE t5.C2='Q' AND t2.c12='R' AND t3.C3 ='S' ORDER BY t5.C3,t2.c1,t3.pk1,t3.pk2;
C1 C2 C3 c1 c12 c2 C1 C2 pk1 C3 pk2
X Q 2 1 R 1 X Y 2 S 1
X Q 2 1 R 1 X Z 2 S 2
X Q 2 2 R 4 X Y 2 S 1
X Q 2 2 R 4 X Z 2 S 2
X Q 2 3 R 9 X Y 2 S 1
X Q 2 3 R 9 X Z 2 S 2
X Q 2 5 R 25 X Y 2 S 1
X Q 2 5 R 25 X Z 2 S 2
X Q 2 6 R 36 X Y 2 S 1
X Q 2 6 R 36 X Z 2 S 2
X Q 2 7 R 49 X Y 2 S 1
X Q 2 7 R 49 X Z 2 S 2
X Q 2 9 R 81 X Y 2 S 1
X Q 2 9 R 81 X Z 2 S 2
X Q 3 1 R 1 X Y 2 S 1
X Q 3 1 R 1 X Z 2 S 2
X Q 3 2 R 4 X Y 2 S 1
X Q 3 2 R 4 X Z 2 S 2
X Q 3 3 R 9 X Y 2 S 1
X Q 3 3 R 9 X Z 2 S 2
X Q 3 5 R 25 X Y 2 S 1
X Q 3 5 R 25 X Z 2 S 2
X Q 3 6 R 36 X Y 2 S 1
X Q 3 6 R 36 X Z 2 S 2
X Q 3 7 R 49 X Y 2 S 1
X Q 3 7 R 49 X Z 2 S 2
X Q 3 9 R 81 X Y 2 S 1
X Q 3 9 R 81 X Z 2 S 2
X Q 5 1 R 1 X Y 2 S 1
X Q 5 1 R 1 X Z 2 S 2
X Q 5 2 R 4 X Y 2 S 1
X Q 5 2 R 4 X Z 2 S 2
X Q 5 3 R 9 X Y 2 S 1
X Q 5 3 R 9 X Z 2 S 2
X Q 5 5 R 25 X Y 2 S 1
X Q 5 5 R 25 X Z 2 S 2
X Q 5 6 R 36 X Y 2 S 1
X Q 5 6 R 36 X Z 2 S 2
X Q 5 7 R 49 X Y 2 S 1
X Q 5 7 R 49 X Z 2 S 2
X Q 5 9 R 81 X Y 2 S 1
X Q 5 9 R 81 X Z 2 S 2
SELECT * FROM t5,t2,t3 WHERE t5.C2='Q' AND t2.c12='R' AND t3.C3 ='S' ORDER BY t5.C3,t2.c1,t3.pk1,t3.pk2;
C1 C2 C3 c1 c12 c2 C1 C2 pk1 C3 pk2
X Q 2 1 R 1 X Y 2 S 1
X Q 2 1 R 1 X Z 2 S 2
X Q 2 2 R 4 X Y 2 S 1
X Q 2 2 R 4 X Z 2 S 2
X Q 2 3 R 9 X Y 2 S 1
X Q 2 3 R 9 X Z 2 S 2
X Q 2 5 R 25 X Y 2 S 1
X Q 2 5 R 25 X Z 2 S 2
X Q 2 6 R 36 X Y 2 S 1
X Q 2 6 R 36 X Z 2 S 2
X Q 2 7 R 49 X Y 2 S 1
X Q 2 7 R 49 X Z 2 S 2
X Q 2 9 R 81 X Y 2 S 1
X Q 2 9 R 81 X Z 2 S 2
X Q 3 1 R 1 X Y 2 S 1
X Q 3 1 R 1 X Z 2 S 2
X Q 3 2 R 4 X Y 2 S 1
X Q 3 2 R 4 X Z 2 S 2
X Q 3 3 R 9 X Y 2 S 1
X Q 3 3 R 9 X Z 2 S 2
X Q 3 5 R 25 X Y 2 S 1
X Q 3 5 R 25 X Z 2 S 2
X Q 3 6 R 36 X Y 2 S 1
X Q 3 6 R 36 X Z 2 S 2
X Q 3 7 R 49 X Y 2 S 1
X Q 3 7 R 49 X Z 2 S 2
X Q 3 9 R 81 X Y 2 S 1
X Q 3 9 R 81 X Z 2 S 2
X Q 5 1 R 1 X Y 2 S 1
X Q 5 1 R 1 X Z 2 S 2
X Q 5 2 R 4 X Y 2 S 1
X Q 5 2 R 4 X Z 2 S 2
X Q 5 3 R 9 X Y 2 S 1
X Q 5 3 R 9 X Z 2 S 2
X Q 5 5 R 25 X Y 2 S 1
X Q 5 5 R 25 X Z 2 S 2
X Q 5 6 R 36 X Y 2 S 1
X Q 5 6 R 36 X Z 2 S 2
X Q 5 7 R 49 X Y 2 S 1
X Q 5 7 R 49 X Z 2 S 2
X Q 5 9 R 81 X Y 2 S 1
X Q 5 9 R 81 X Z 2 S 2
CREATE TABLE t4 (C1 CHAR(1) PRIMARY KEY, B1 BIT(1), B2 BIT(1) NOT NULL DEFAULT 0, C2 CHAR(1) NOT NULL DEFAULT 'A') ENGINE = 'NDB' ;
INSERT INTO t4 SET C1 = 1;
SELECT C1,HEX(B1),HEX(B2) FROM t4 ORDER BY C1;
C1 HEX(B1) HEX(B2)
1 NULL 0
SELECT C1,HEX(B1),HEX(B2) FROM t4 ORDER BY C1;
C1 HEX(B1) HEX(B2)
1 NULL 0
CREATE TABLE t7 (C1 INT PRIMARY KEY, C2 INT) ENGINE = 'NDB' ;
--- on slave: original values ---
INSERT INTO t7 VALUES (1,3), (2,6), (3,9);
SELECT * FROM t7 ORDER BY C1;
C1 C2
1 3
2 6
3 9
--- on master: new values inserted ---
INSERT INTO t7 VALUES (1,2), (2,4), (3,6);
SELECT * FROM t7 ORDER BY C1;
C1 C2
1 2
2 4
3 6
--- on slave: old values should be overwritten by replicated values ---
SELECT * FROM t7 ORDER BY C1;
C1 C2
1 2
2 4
3 6
--- on master ---
DROP TABLE t7;
CREATE TABLE t7 (a INT PRIMARY KEY, b INT UNIQUE, c INT UNIQUE) ENGINE = 'NDB' ;
INSERT INTO t7 VALUES (99,99,99);
INSERT INTO t7 VALUES (99,22,33);
ERROR 23000: Duplicate entry '99' for key 1
INSERT INTO t7 VALUES (11,99,33);
ERROR 23000: Duplicate entry '11' for key 1
INSERT INTO t7 VALUES (11,22,99);
ERROR 23000: Duplicate entry '11' for key 1
SELECT * FROM t7 ORDER BY a;
a b c
99 99 99
--- on slave ---
SELECT * FROM t7 ORDER BY a;
a b c
99 99 99
INSERT INTO t7 VALUES (1,2,3), (2,4,6), (3,6,9);
SELECT * FROM t7 ORDER BY a;
a b c
1 2 3
2 4 6
3 6 9
99 99 99
--- on master ---
INSERT INTO t7 VALUES (2,4,8);
--- on slave ---
SELECT * FROM t7 ORDER BY a;
a b c
1 2 3
2 4 8
3 6 9
99 99 99
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7;

View file

@ -6,6 +6,7 @@ foo CREATE DATABASE `foo` /*!40100 DEFAULT CHARACTER SET latin1 */
show schemas;
Database
information_schema
cluster_replication
foo
mysql
test

View file

@ -53,6 +53,7 @@ Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length I
show databases;
Database
information_schema
cluster_replication
mysql
test
show databases like "test%";

View file

@ -1409,22 +1409,52 @@ DROP TABLE t5;
CREATE TABLE `t5` (
`a` int(11) NOT NULL auto_increment,
b char(12),
b blob(12),
KEY (`a`)
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (32, "foo");
INSERT INTO t5 VALUES (23, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (3, "foo");
INSERT INTO t5 VALUES (NULL, "foo");
INSERT INTO t5 VALUES (NULL, "We the people");
INSERT INTO t5 VALUES (NULL, "in order to form a more pefect union");
INSERT INTO t5 VALUES (NULL, "establish justice");
INSERT INTO t5 VALUES (NULL, "foo grok ");
INSERT INTO t5 VALUES (32, "ensure domestic tranquility");
INSERT INTO t5 VALUES (23, "provide for the common defense");
INSERT INTO t5 VALUES (NULL, "fo fooo");
INSERT INTO t5 VALUES (NULL, "foo just naother bit of text");
INSERT INTO t5 VALUES (3, "foo this is mine to think about");
INSERT INTO t5 VALUES (NULL, "promote the general welfare");
SELECT * FROM t5;
SELECT b FROM t5;
SELECT b FROM t5 WHERE a =3;
SELECT b FROM t5 WHERE a IN (32, 23, 5);
#More blob tests
DROP TABLE t5;
CREATE TABLE `t5` (
`a` int(11) NOT NULL auto_increment,
b blob(12),
c blob(12),
KEY (`a`)
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
INSERT INTO t5 VALUES (NULL, "foo", "grok this!");
INSERT INTO t5 VALUES (NULL, "We the people", NULL);
INSERT INTO t5 VALUES (NULL, "in order to form a more peefect union", "secure the blessing of liberty");
INSERT INTO t5 VALUES (NULL, "establish justice", "to ourselves and");
INSERT INTO t5 VALUES (32, "ensure domestic tranquility", NULL);
INSERT INTO t5 VALUES (23, "provide for the common defense", "posterity");
INSERT INTO t5 VALUES (NULL, "promote the general welfare", "do ordain");
SELECT * FROM t5;
SELECT b FROM t5;
SELECT b FROM t5 WHERE a =3;
SELECT b FROM t5 WHERE a IN (32, 23, 5);
SELECT c FROM t5;
SELECT c FROM t5 WHERE a =3;
SELECT c FROM t5 WHERE a IN (32, 23, 5);
#
# Cleanup, test is over

View file

@ -18,6 +18,11 @@ group_min_max : Bug #15448
innodb_concurrent : Results are not deterministic, Elliot will fix (BUG#3300)
subselect : Bug#15706
type_time : Bug#15805
ps_7ndb : dbug assert in RBR mode when executing test suite
rpl_ddl : Bug#15963 SBR does not show "Definer" correctly
events : Affects flush test case. A table lock not released somewhere
ndb_autodiscover : TBF with CR
ndb_autodiscover2 : TBF with CR
ndb_binlog_basic : Results are not deterministic, Tomas will fix
rpl_ndb_basic : Bug#16228
rpl_sp : Bug #16456

View file

@ -518,9 +518,6 @@ echo $novar1;
--error 1
--exec echo "let $=hi;" | $MYSQL_TEST 2>&1
--error 1
--exec echo "let hi=hi;" | $MYSQL_TEST 2>&1
--error 1
--exec echo "let $1 hi;" | $MYSQL_TEST 2>&1

View file

@ -142,23 +142,19 @@ INSERT INTO t1 VALUES (1,2,0),(18,19,4),(20,21,0);
select c from t1 order by c;
drop table t1;
--disable_ps_protocol
create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
engine=ndb;
insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
create index c on t1(c);
connection server2;
select * from t1 where b = 'two';
connection server1;
alter table t1 drop index c;
connection server2;
# This should fail since index information is not automatically refreshed
--error 1015
select * from t1 where b = 'two';
select * from t1 where b = 'two';
connection server1;
drop table t1;
--enable_ps_protocol
## Test moved to ndb_alter_table_row|stmt respectively as behaviour differs
#create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
#engine=ndb;
#insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
#create index c on t1(c);
#connection server2;
#select * from t1 where c = 'two';
#connection server1;
#alter table t1 drop index c;
#connection server2;
#select * from t1 where c = 'two';
#connection server1;
#drop table t1;
#--disable_warnings
#DROP TABLE IF EXISTS t2;
@ -183,29 +179,32 @@ drop table t1;
#select count(*) from t2;
#drop table t2;
connection server1;
create table t3 (a int primary key) engine=ndbcluster;
## Test moved to ndb_alter_table_row|stmt respectively as behaviour differs
#connection server1;
#create table t3 (a int primary key) engine=ndbcluster;
connection server2;
begin;
insert into t3 values (1);
#connection server2;
#begin;
#insert into t3 values (1);
connection server1;
alter table t3 rename t4;
#connection server1;
#alter table t3 rename t4;
connection server2;
# This should work as transaction is ongoing...
delete from t3;
insert into t3 values (1);
commit;
#connection server2;
## with rbr the below will not work as the "alter" event
## explicitly invalidates the dictionary cache.
### This should work as transaction is ongoing...
##delete from t3;
##insert into t3 values (1);
#commit;
# This should fail as its a new transaction
--error 1015
select * from t3;
select * from t4;
drop table t4;
show tables;
connection server1;
## This should fail as its a new transaction
#--error 1146
#select * from t3;
#select * from t4;
#drop table t4;
#show tables;
#connection server1;
create table t1 (
ai bigint auto_increment,

View file

@ -0,0 +1,48 @@
-- source include/have_ndb.inc
-- source include/have_multi_ndb.inc
-- source include/not_embedded.inc
-- source include/have_binlog_format_row.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
connection server1;
create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
engine=ndb;
insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
create index c on t1(c);
connection server2;
select * from t1 where c = 'two';
connection server1;
alter table t1 drop index c;
connection server2;
select * from t1 where c = 'two';
connection server1;
drop table t1;
connection server1;
create table t3 (a int primary key) engine=ndbcluster;
connection server2;
begin;
insert into t3 values (1);
connection server1;
alter table t3 rename t4;
connection server2;
# with rbr the below will not work as the "alter" event
# explicitly invalidates the dictionary cache.
## This should work as transaction is ongoing...
#delete from t3;
#insert into t3 values (1);
commit;
# This should fail as its a new transaction
--error 1146
select * from t3;
select * from t4;
drop table t4;
show tables;
connection server1;

View file

@ -0,0 +1,51 @@
-- source include/have_ndb.inc
-- source include/have_multi_ndb.inc
-- source include/not_embedded.inc
-- source include/have_binlog_format_statement.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
connection server1;
create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
engine=ndb;
insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
create index c on t1(c);
connection server2;
select * from t1 where c = 'two';
connection server1;
alter table t1 drop index c;
connection server2;
-- error 1015
select * from t1 where c = 'two';
select * from t1 where c = 'two';
connection server1;
drop table t1;
connection server1;
create table t3 (a int primary key) engine=ndbcluster;
connection server2;
begin;
insert into t3 values (1);
connection server1;
alter table t3 rename t4;
connection server2;
# with rbr the below will not work as the "alter" event
# explicitly invalidates the dictionary cache.
# This should work as transaction is ongoing...
delete from t3;
insert into t3 values (1);
commit;
# This should fail as its a new transaction
--error 1015
select * from t3;
select * from t4;
drop table t4;
show tables;
connection server1;

View file

@ -6,6 +6,17 @@ DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7;
drop database if exists mysqltest;
--enable_warnings
# workaround for bug#16445
# remove to reproduce bug and run tests drom ndb start
# and with ndb_autodiscover disabled
CREATE TABLE t1 (
pk1 INT NOT NULL PRIMARY KEY,
attr1 INT NOT NULL,
attr2 INT,
attr3 VARCHAR(10)
) ENGINE=ndbcluster;
drop table t1;
#
# Basic test to show that the NDB
# table handler is working

View file

@ -0,0 +1,76 @@
-- source include/have_ndb.inc
-- source include/have_binlog_format_row.inc
--disable_warnings
drop table if exists t1, t2;
drop database if exists mysqltest;
create database mysqltest;
use mysqltest;
drop database mysqltest;
use test;
--enable_warnings
#
# basic insert, update, delete test, alter, rename, drop
# check that binlog_index gets the right info
#
create table t1 (a int primary key) engine=ndb;
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
save_master_pos;
--replace_column 1 #
select @max_epoch:=max(epoch)-1 from cluster_replication.binlog_index;
delete from t1;
alter table t1 add (b int);
insert into t1 values (3,3),(4,4);
alter table t1 rename t2;
# get all in one epoch
begin;
insert into t2 values (1,1),(2,2);
update t2 set b=1 where a=3;
delete from t2 where a=4;
commit;
drop table t2;
# check that above is ok
# (save_master_pos waits for last gcp to complete, ensuring that we have
# the expected data in the binlog)
save_master_pos;
select inserts from cluster_replication.binlog_index where epoch > @max_epoch and inserts > 5;
select deletes from cluster_replication.binlog_index where epoch > @max_epoch and deletes > 5;
select inserts,updates,deletes from
cluster_replication.binlog_index where epoch > @max_epoch and updates > 0;
select schemaops from
cluster_replication.binlog_index where epoch > @max_epoch and schemaops > 0;
#
# check that purge clears the binlog_index
#
flush logs;
--sleep 1
purge master logs before now();
select count(*) from cluster_replication.binlog_index;
#
# several tables in different databases
# check that same table name in different databases don't mix up
#
create table t1 (a int primary key, b int) engine=ndb;
create database mysqltest;
use mysqltest;
create table t1 (c int, d int primary key) engine=ndb;
use test;
insert into mysqltest.t1 values (2,1),(2,2);
save_master_pos;
--replace_column 1 #
select @max_epoch:=max(epoch)-1 from cluster_replication.binlog_index;
drop table t1;
drop database mysqltest;
select inserts,updates,deletes from
cluster_replication.binlog_index where epoch > @max_epoch and inserts > 0;
select schemaops from
cluster_replication.binlog_index where epoch > @max_epoch and schemaops > 0;

View file

@ -0,0 +1,70 @@
-- source include/have_ndb.inc
-- source include/have_multi_ndb.inc
-- source include/have_binlog_format_row.inc
--disable_warnings
connection server2;
drop table if exists t1,t2;
connection server1;
drop table if exists t1,t2;
--enable_warnings
#
# basic test to see if one server sees the table from the other
# and sets up the replication correctly
#
# no tables and nothing in cluster_replication.binlog_index;
connection server1;
SHOW TABLES;
# create table on the other server
connection server2;
CREATE TABLE t2 (a INT PRIMARY KEY, b int) ENGINE = NDB;
# make sure the first mysql server knows about this table
connection server1;
show tables;
# insert something on server2
connection server2;
INSERT INTO t2 VALUES (1,1),(2,2);
select * from t2 order by a;
save_master_pos;
--replace_column 1 <the_epoch>
SELECT @the_epoch:=epoch,inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index ORDER BY epoch DESC LIMIT 1;
let $the_epoch= `SELECT @the_epoch`;
# see if we got something on server1
connection server1;
SELECT * FROM t2 ORDER BY a;
--replace_result $the_epoch <the_epoch>
eval SELECT inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index WHERE epoch=$the_epoch;
# drop the table on server1
DROP TABLE t2;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE = NDB;
INSERT INTO t1 VALUES (1),(2);
save_master_pos;
--replace_column 1 <the_epoch2>
SELECT @the_epoch2:=epoch,inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index ORDER BY epoch DESC LIMIT 1;
let $the_epoch2= `SELECT @the_epoch2`;
--replace_result $the_epoch <the_epoch> $the_epoch2 <the_epoch2>
eval SELECT inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index WHERE epoch > $the_epoch AND epoch < $the_epoch2;
drop table t1;
# flush on server2
connection server2;
SHOW TABLES;
--replace_result $the_epoch <the_epoch> $the_epoch2 <the_epoch2>
eval SELECT inserts,updates,deletes,schemaops FROM
cluster_replication.binlog_index WHERE epoch > $the_epoch AND epoch < $the_epoch2;
# reset
connection server1;

View file

@ -1,9 +1,13 @@
-- source include/have_ndb.inc
-- source include/have_multi_ndb.inc
-- source include/not_embedded.inc
-- source include/have_binlog_format_statement.inc
--disable_warnings
connection server2;
drop table if exists t1, t2, t3, t4;
connection server1;
drop table if exists t1, t2, t3, t4;
--enable_warnings

View file

@ -0,0 +1,78 @@
-- source include/have_ndb.inc
-- source include/have_multi_ndb.inc
-- source include/not_embedded.inc
-- source include/have_binlog_format_row.inc
--disable_warnings
connection server2;
drop table if exists t1, t2, t3, t4;
connection server1;
drop table if exists t1, t2, t3, t4;
--enable_warnings
flush status;
# Create test tables on server1
create table t1 (a int) engine=ndbcluster;
create table t2 (a int) engine=ndbcluster;
insert into t1 value (2);
insert into t2 value (3);
select * from t1;
select * from t2;
show status like 'handler_discover%';
# Check dropping and recreating table on same server
connect (con1,localhost,,,test);
connect (con2,localhost,,,test);
connection con1;
select * from t1;
connection con2;
drop table t1;
create table t1 (a int) engine=ndbcluster;
insert into t1 value (2);
connection con1;
select * from t1;
# Check dropping and recreating table on different server
connection server2;
show status like 'handler_discover%';
drop table t1;
create table t1 (a int) engine=ndbcluster;
insert into t1 value (2);
connection server1;
## Currently a retry is required remotely
#--error 1412
#select * from t1;
#show warnings;
#flush table t1;
# Table definition change should be propagated automatically
select * from t1;
# Connect to server2 and use the tables from there
connection server2;
flush status;
select * from t1;
update t1 set a=3 where a=2;
show status like 'handler_discover%';
# Create a new table on server2
create table t3 (a int not null primary key, b varchar(22),
c int, last_col text) engine=ndb;
insert into t3 values(1, 'Hi!', 89, 'Longtext column');
create table t4 (pk int primary key, b int) engine=ndb;
# Check that the tables are accessible from server1
connection server1;
select * from t1;
select * from t3;
show status like 'handler_discover%';
show tables like 't4';
show status like 'handler_discover%';
show tables;
drop table t1, t2, t3, t4;
connection server2;
drop table t1, t3, t4;
# End of 4.1 tests

View file

@ -0,0 +1,207 @@
#
# Currently this test only runs in the source tree with the
# ndb/test programs compiled.
# invoke with: ./mysql-test-run --ndb-extra-test --do-test=rpl_ndb_bank
#
# 1. start a "bank" application running on the master cluster
# 2. perform online sync of slave
# 3. periodically check consistency of slave
# 4. stop the bank application
# 5. check that the slave and master BANK databases are the same
#
# kill any trailing processes
--system killall lt-bankTransactionMaker lt-bankTimer lt-bankMakeGL || true
--source include/have_ndb.inc
--source include/have_ndb_extra.inc
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
--disable_warnings
# initialize master
--connection master
CREATE DATABASE IF NOT EXISTS BANK;
DROP DATABASE BANK;
CREATE DATABASE BANK default charset=latin1 default collate=latin1_bin;
--enable_warnings
#
# These tables should correspond to the table definitions in
# storage/ndb/test/src/NDBT_Tables.cpp
#
--connection master
USE BANK;
CREATE TABLE GL ( TIME BIGINT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
BALANCE INT UNSIGNED NOT NULL,
DEPOSIT_COUNT INT UNSIGNED NOT NULL,
DEPOSIT_SUM INT UNSIGNED NOT NULL,
WITHDRAWAL_COUNT INT UNSIGNED NOT NULL,
WITHDRAWAL_SUM INT UNSIGNED NOT NULL,
PURGED INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (TIME,ACCOUNT_TYPE))
ENGINE = NDB;
CREATE TABLE ACCOUNT ( ACCOUNT_ID INT UNSIGNED NOT NULL,
OWNER INT UNSIGNED NOT NULL,
BALANCE INT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (ACCOUNT_ID))
ENGINE = NDB;
CREATE TABLE TRANSACTION ( TRANSACTION_ID BIGINT UNSIGNED NOT NULL,
ACCOUNT INT UNSIGNED NOT NULL,
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
OTHER_ACCOUNT INT UNSIGNED NOT NULL,
TRANSACTION_TYPE INT UNSIGNED NOT NULL,
TIME BIGINT UNSIGNED NOT NULL,
AMOUNT INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (TRANSACTION_ID,ACCOUNT))
ENGINE = NDB;
CREATE TABLE SYSTEM_VALUES ( SYSTEM_VALUES_ID INT UNSIGNED NOT NULL,
VALUE BIGINT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (SYSTEM_VALUES_ID))
ENGINE = NDB;
CREATE TABLE ACCOUNT_TYPE ( ACCOUNT_TYPE_ID INT UNSIGNED NOT NULL,
DESCRIPTION CHAR(64) NOT NULL,
PRIMARY KEY USING HASH (ACCOUNT_TYPE_ID))
ENGINE = NDB;
#
# create "BANK" application
#
--exec NDB_CONNECTSTRING=localhost:$NDBCLUSTER_PORT ../storage/ndb/test/ndbapi/bank/bankCreator >> $NDB_TOOLS_OUTPUT
#
# start main loop
# repeat backup-restore-check
#
# set this high if testing to run many syncs in loop
--let $2=1
while ($2)
{
#
# start "BANK" application
#
--exec NDB_CONNECTSTRING=localhost:$NDBCLUSTER_PORT ../storage/ndb/test/ndbapi/bank/bankTimer -w 5 >> $NDB_TOOLS_OUTPUT &
--exec NDB_CONNECTSTRING=localhost:$NDBCLUSTER_PORT ../storage/ndb/test/ndbapi/bank/bankMakeGL >> $NDB_TOOLS_OUTPUT &
--exec NDB_CONNECTSTRING=localhost:$NDBCLUSTER_PORT ../storage/ndb/test/ndbapi/bank/bankTransactionMaker >> $NDB_TOOLS_OUTPUT &
#
# let the "BANK" run for a while
#
--sleep 5
--disable_warnings
# initialize slave for sync
--connection slave
STOP SLAVE;
RESET SLAVE;
# to make sure we drop any ndbcluster tables
CREATE DATABASE IF NOT EXISTS BANK;
DROP DATABASE BANK;
# create database
CREATE DATABASE BANK;
--enable_warnings
#
# Time to sync the slave:
# start by taking a backup on master
--connection master
RESET MASTER;
--exec $NDB_MGM --no-defaults --ndb-connectstring=localhost:$NDBCLUSTER_PORT -e "start backup" >> $NDB_TOOLS_OUTPUT
# there is no neat way to find the backupid, this is a hack to find it...
--exec $NDB_TOOLS_DIR/ndb_select_all --ndb-connectstring=localhost:$NDBCLUSTER_PORT -d sys -D , SYSTAB_0 | grep 520093696 > var/tmp.dat
CREATE TABLE IF NOT EXISTS cluster_replication.backup_info (id INT, backup_id INT) ENGINE = HEAP;
DELETE FROM cluster_replication.backup_info;
LOAD DATA INFILE '../../var/tmp.dat' INTO TABLE cluster_replication.backup_info FIELDS TERMINATED BY ',';
--replace_column 1 <the_backup_id>
SELECT @the_backup_id:=backup_id FROM cluster_replication.backup_info;
let the_backup_id=`select @the_backup_id`;
# restore on slave, first check that nothing is there
--connection slave
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -p 8 -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -p 8 -b $the_backup_id -n 2 -r -e --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
#
# now setup replication to continue from last epoch
# 1. get apply_status epoch from slave
# 2. get corresponding _next_ binlog postition from master
# 3. change master on slave
# 4. start the replication
# 1.
--connection slave
--replace_column 1 <the_epoch>
SELECT @the_epoch:=MAX(epoch) FROM cluster_replication.apply_status;
--let $the_epoch= `select @the_epoch`
# 2.
--connection master
--replace_result $the_epoch <the_epoch>
--replace_column 1 <the_pos>
eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
FROM cluster_replication.binlog_index WHERE epoch > $the_epoch ORDER BY epoch ASC LIMIT 1;
--let $the_pos= `SELECT @the_pos`
--let $the_file= `SELECT @the_file`
# 3.
--connection slave
--replace_result $the_pos <the_pos>
eval CHANGE MASTER TO
master_log_file = '$the_file',
master_log_pos = $the_pos;
# 4.
--connection slave
START SLAVE;
#
# Now loop and check consistency every 2 seconds on slave
#
--connection slave
--let $1=10
while ($1)
{
--sleep 2
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 <Slave_IO_State> 7 <Read_Master_Log_Pos> 8 <Relay_Log_File> 9 <Relay_Log_Pos> 16 <Replicate_Ignore_Table> 22 <Exec_Master_Log_Pos> 23 <Relay_Log_Space> 33 <Seconds_Behind_Master>
SHOW SLAVE STATUS;
STOP SLAVE;
--exec NDB_CONNECTSTRING=localhost:$NDBCLUSTER_PORT_SLAVE ../storage/ndb/test/ndbapi/bank/bankValidateAllGLs >> $NDB_TOOLS_OUTPUT
START SLAVE;
--dec $1
}
#
# Stop transactions
#
--exec killall lt-bankTransactionMaker lt-bankTimer lt-bankMakeGL
#
# Check that the databases are the same on slave and master
# 1. dump database BANK on both master and slave
# 2. compare, there should be no difference
#
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info BANK ACCOUNT_TYPE ACCOUNT GL TRANSACTION > ./var/tmp/master_BANK.sql
--connection master
use test;
create table t1 (a int primary key) engine=ndb;
insert into t1 values (1);
--sync_slave_with_master
--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info BANK ACCOUNT_TYPE ACCOUNT GL TRANSACTION > ./var/tmp/slave_BANK.sql
--connection master
drop table t1;
--exec diff ./var/tmp/master_BANK.sql ./var/tmp/slave_BANK.sql
--dec $2
}

View file

@ -0,0 +1,146 @@
--source include/have_ndb.inc
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
#
# Bug #11087
#
# connect to the master and create tabe t1 in gotoslave database
--connection master
CREATE TABLE `t1` ( `nid` int(11) NOT NULL default '0',
`nom` char(4) default NULL,
`prenom` char(4) default NULL,
PRIMARY KEY (`nid`))
ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES(1,"XYZ1","ABC1");
select * from t1 order by nid;
--sync_slave_with_master
# connect to slave and ensure data it there.
--connection slave
select * from t1 order by nid;
--connection master
delete from t1;
INSERT INTO t1 VALUES(1,"XYZ2","ABC2");
# Make sure all rows are on the master
select * from t1 order by nid;
# make sure all rows are on the slave.
--sync_slave_with_master
--connection slave
# Bug #11087 would have row with nid 2 missing
select * from t1 order by nid;
--connection master
DROP table t1;
#
# Test replication of table with no primary key
#
--connection master
CREATE TABLE `t1` ( `nid` int(11) NOT NULL default '0',
`nom` char(4) default NULL,
`prenom` char(4) default NULL)
ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES(1,"XYZ1","ABC1"),(2,"AAA","BBB"),(3,"CCC","DDD");
select * from t1 order by nid;
--sync_slave_with_master
# connect to slave and ensure data it there.
--connection slave
select * from t1 order by nid;
--connection master
delete from t1 where nid = 2;
INSERT INTO t1 VALUES(4,"EEE","FFF");
# Make sure all rows are on the master
select * from t1 order by nid;
# make sure all rows are on the slave.
--sync_slave_with_master
--connection slave
select * from t1 order by nid;
--connection master
UPDATE t1 set nid=nid+1;
UPDATE t1 set nom="CCP" where nid = 4;
select * from t1 order by nid;
# make sure all rows are on the slave.
--sync_slave_with_master
--connection slave
select * from t1 order by nid;
--connection master
DROP table t1;
##################################################################
#
# Check that retries are made on the slave on some temporary errors
#
#
# 1. Deadlock
#
--connection master
CREATE TABLE `t1` ( `nid` int(11) NOT NULL default '0',
`nom` char(4) default NULL,
`prenom` char(4) default NULL,
PRIMARY KEY USING HASH (`nid`))
ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES(1,"XYZ1","ABC1");
# cause a lock on that row on the slave
--sync_slave_with_master
--connection slave
BEGIN;
UPDATE t1 SET `nom`="LOCK" WHERE `nid`=1;
# set number of retries low so we fail the retries
set GLOBAL slave_transaction_retries=1;
# now do a change to this row on the master
# will deadlock on the slave because of lock above
--connection master
UPDATE t1 SET `nom`="DEAD" WHERE `nid`=1;
# wait for deadlock to be detected
# sleep longer than dead lock detection timeout in config
# we do this 2 times, once with few retries to verify that we
# get a failure with the set sleep, and once with the _same_
# sleep, but with more retries to get it to succeed
--sleep 5
# replication should have stopped, since max retries where not enough
# verify with show slave status
--connection slave
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 <Slave_IO_State> 7 <Read_Master_Log_Pos> 8 <Relay_Log_File> 9 <Relay_Log_Pos> 16 <Replicate_Ignore_Table> 22 <Exec_Master_Log_Pos> 23 <Relay_Log_Space> 33 <Seconds_Behind_Master>
SHOW SLAVE STATUS;
# now set max retries high enough to succeed, and start slave again
set GLOBAL slave_transaction_retries=10;
START SLAVE;
# wait for deadlock to be detected and retried
# should be the same sleep as above for test to be valid
--sleep 5
# commit transaction to release lock on row and let replication succeed
select * from t1 order by nid;
COMMIT;
# verify that the row succeded to be applied on the slave
--connection master
--sync_slave_with_master
--connection slave
select * from t1 order by nid;
# cleanup
--connection master
DROP TABLE t1;

View file

@ -0,0 +1,87 @@
--source include/have_ndb.inc
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
#
# Basic test of disk tables for NDB
#
#
# Start by creating a logfile group
#
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
UNDO_BUFFER_SIZE = 1M
ENGINE=NDB;
alter logfile group lg1
add undofile 'undofile02.dat'
initial_size 4M engine=ndb;
#
# Create a tablespace connected to the logfile group
#
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
INITIAL_SIZE 12M
ENGINE NDB;
alter tablespace ts1
add datafile 'datafile02.dat'
initial_size 4M engine=ndb;
#
# Create a table using this tablespace
#
CREATE TABLE t1
(pk1 int not null primary key, b int not null, c int not null)
tablespace ts1 storage disk
engine ndb;
#
# insert some data
#
insert into t1 values (1,2,3);
select * from t1 order by pk1;
#
# check that the data is also on the slave
#
--sync_slave_with_master
--connection slave
select * from t1 order by pk1;
#
# view the binlog
#
--connection master
let $VERSION=`select version()`;
--replace_result $VERSION VERSION
show binlog events;
#
# cleanup
#
drop table t1;
alter tablespace ts1
drop datafile 'datafile.dat'
engine=ndb;
alter tablespace ts1
drop datafile 'datafile02.dat'
engine=ndb;
DROP TABLESPACE ts1 ENGINE=NDB;
DROP LOGFILE GROUP lg1 ENGINE=NDB;
--sync_slave_with_master

View file

@ -0,0 +1,111 @@
--source include/have_ndb.inc
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
#
# Currently test only works with ndb since it retrieves "old"
# binlog positions with cluster_replication.binlog_index and apply_status;
#
# create a table with one row
CREATE TABLE t1 (c1 CHAR(15), c2 CHAR(15), c3 INT, PRIMARY KEY (c3)) ENGINE = NDB ;
INSERT INTO t1 VALUES ("row1","will go away",1);
SELECT * FROM t1 ORDER BY c3;
# sync slave and retrieve epoch
sync_slave_with_master;
--replace_column 1 <the_epoch>
SELECT @the_epoch:=MAX(epoch) FROM cluster_replication.apply_status;
let $the_epoch= `select @the_epoch` ;
SELECT * FROM t1 ORDER BY c3;
# get the master binlog pos from the epoch
connection master;
--replace_result $the_epoch <the_epoch>
--replace_column 1 <the_pos>
eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
FROM cluster_replication.binlog_index WHERE epoch = $the_epoch ;
let $the_pos= `SELECT @the_pos` ;
let $the_file= `SELECT @the_file` ;
# insert some more values
INSERT INTO t1 VALUES ("row2","will go away",2),("row3","will change",3),("row4","D",4);
DELETE FROM t1 WHERE c3 = 1;
UPDATE t1 SET c2="should go away" WHERE c3 = 2;
UPDATE t1 SET c2="C" WHERE c3 = 3;
DELETE FROM t1 WHERE c3 = 2;
SELECT * FROM t1 ORDER BY c3;
# check that we have it on the slave
--sync_slave_with_master
--connection slave
SELECT * FROM t1 ORDER BY c3;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 <Slave_IO_State> 7 <Read_Master_Log_Pos> 8 <Relay_Log_File> 9 <Relay_Log_Pos> 16 <Replicate_Ignore_Table> 22 <Exec_Master_Log_Pos> 23 <Relay_Log_Space> 33 <Seconds_Behind_Master>
SHOW SLAVE STATUS;
# stop slave and reset position to before the last changes
STOP SLAVE;
--replace_result $the_pos <the_pos>
eval CHANGE MASTER TO
master_log_file = '$the_file',
master_log_pos = $the_pos ;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 <Slave_IO_State> 7 <Read_Master_Log_Pos> 8 <Relay_Log_File> 9 <Relay_Log_Pos> 16 <Replicate_Ignore_Table> 22 <Exec_Master_Log_Pos> 23 <Relay_Log_Space> 33 <Seconds_Behind_Master>
SHOW SLAVE STATUS;
# start the slave again
# -> same events should have been applied again
# e.g. inserting rows that already there
# deleting a row which is not there
# updating a row which is not there
START SLAVE;
--connection master
SELECT * FROM t1 ORDER BY c3;
--sync_slave_with_master
--connection slave
SELECT * FROM t1 ORDER BY c3;
STOP SLAVE;
#
# cleanup
#
--connection master
DROP TABLE t1;
RESET master;
--connection slave
DROP TABLE t1;
RESET slave;
START SLAVE;
#
# Test that we can handle update of a row that does not exist on the slave
# will trigger usage of AO_IgnoreError on slave side so that the INSERT
# still succeeds even if the replication of the UPDATE generates an error.
#
--connection master
CREATE TABLE t1 (c1 CHAR(15) NOT NULL, c2 CHAR(15) NOT NULL, c3 INT NOT NULL, PRIMARY KEY (c3)) ENGINE = NDB ;
INSERT INTO t1 VALUES ("row1","remove on slave",1);
--sync_slave_with_master
--connection slave
DELETE FROM t1;
--connection master
BEGIN;
UPDATE t1 SET c2="does not exist" WHERE c3=1;
INSERT INTO t1 VALUES ("row2","new on slave",2);
COMMIT;
--sync_slave_with_master
--connection slave
SELECT * FROM t1;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 <Slave_IO_State> 7 <Read_Master_Log_Pos> 8 <Relay_Log_File> 9 <Relay_Log_Pos> 16 <Replicate_Ignore_Table> 22 <Exec_Master_Log_Pos> 23 <Relay_Log_Space> 33 <Seconds_Behind_Master>
SHOW SLAVE STATUS;

View file

@ -0,0 +1,66 @@
#
# Currently this test only runs in the source tree with the
# ndb/test programs compiled.
# invoke with: ./mysql-test-run --ndb-extra-test --do-test=rpl_ndb_load
#
--source include/have_ndb.inc
--source include/have_ndb_extra.inc
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
--disable_warnings
# reset master
connection master;
DROP DATABASE IF EXISTS TEST_DB;
CREATE DATABASE TEST_DB;
--enable_warnings
#
# These tables should correspond to the table definitions in
# storage/ndb/test/ndbapi/bench/
#
connection master;
USE TEST_DB;
CREATE TABLE SUBSCRIBER
( NUMBER CHAR(12) BINARY NOT NULL,
NAME CHAR(32) BINARY NOT NULL,
GROUP_ID INT UNSIGNED NOT NULL,
LOCATION INT UNSIGNED NOT NULL,
SESSIONS INT UNSIGNED NOT NULL,
CHANGED_BY CHAR(32) BINARY NOT NULL,
CHANGED_TIME CHAR(32) BINARY NOT NULL,
PRIMARY KEY USING HASH (NUMBER))
ENGINE = NDB;
CREATE TABLE GROUP_T
( GROUP_ID INT UNSIGNED NOT NULL,
GROUP_NAME CHAR(32) BINARY NOT NULL,
ALLOW_READ CHAR(1) BINARY NOT NULL,
ALLOW_INSERT INT UNSIGNED NOT NULL,
ALLOW_DELETE INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (GROUP_ID))
ENGINE = NDB;
CREATE TABLE SESSION
( NUMBER CHAR(12) BINARY NOT NULL,
SERVER_ID INT UNSIGNED NOT NULL,
DATA VARBINARY(1998) NOT NULL,
PRIMARY KEY USING HASH (NUMBER,SERVER_ID))
ENGINE = NDB;
CREATE TABLE SERVER
( SUFFIX CHAR(2) BINARY NOT NULL,
SERVER_ID INT UNSIGNED NOT NULL,
NAME CHAR(32) BINARY NOT NULL,
NO_OF_READ INT UNSIGNED NOT NULL,
NO_OF_INSERT INT UNSIGNED NOT NULL,
NO_OF_DELETE INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (SUFFIX, SERVER_ID))
ENGINE = NDB;
#
# start "load" application
#
--exec NDB_CONNECTSTRING=localhost:$NDBCLUSTER_PORT ../storage/ndb/test/ndbapi/DbCreate >> $NDB_TOOLS_OUTPUT
--exec NDB_CONNECTSTRING=localhost:$NDBCLUSTER_PORT ../storage/ndb/test/ndbapi/DbAsyncGenerator >> $NDB_TOOLS_OUTPUT

View file

@ -0,0 +1,71 @@
--source include/have_ndb.inc
--source include/have_multi_ndb.inc
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
# note: server2 is another "master" connected to the master cluster
#
# Currently test only works with ndb since it retrieves "old"
# binlog positions with cluster_replication.binlog_index and apply_status;
#
# create a table with one row, and make sure the other "master" gets it
CREATE TABLE t1 (c1 CHAR(15), c2 CHAR(15), c3 INT, PRIMARY KEY (c3)) ENGINE = NDB ;
connection server2;
reset master;
SHOW TABLES;
connection master;
INSERT INTO t1 VALUES ("row1","will go away",1);
SELECT * FROM t1 ORDER BY c3;
connection server2;
SELECT * FROM t1 ORDER BY c3;
# sync slave and retrieve epoch and stop the slave
connection master;
sync_slave_with_master;
--replace_column 1 <the_epoch>
SELECT @the_epoch:=MAX(epoch) FROM cluster_replication.apply_status;
let $the_epoch= `select @the_epoch` ;
SELECT * FROM t1 ORDER BY c3;
stop slave;
# get the master binlog pos from the epoch, from the _other_ "master", server2
connection server2;
--replace_result $the_epoch <the_epoch>
eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
FROM cluster_replication.binlog_index WHERE epoch = $the_epoch ;
let $the_pos= `SELECT @the_pos` ;
let $the_file= `SELECT @the_file` ;
# now connect the slave to the _other_ "master"
connection slave;
--replace_result $MASTER_MYPORT1 <MASTER_PORT1>
eval CHANGE MASTER TO
master_port=$MASTER_MYPORT1,
master_log_file = '$the_file',
master_log_pos = $the_pos ;
start slave;
# insert some more values on the first master
connection master;
INSERT INTO t1 VALUES ("row2","will go away",2),("row3","will change",3),("row4","D",4);
DELETE FROM t1 WHERE c3 = 1;
UPDATE t1 SET c2="should go away" WHERE c3 = 2;
UPDATE t1 SET c2="C" WHERE c3 = 3;
DELETE FROM t1 WHERE c3 = 2;
SELECT * FROM t1 ORDER BY c3;
save_master_pos;
# insert another row, and check that we have it on the slave
connection server2;
INSERT INTO t1 VALUES ("row5","E",5);
SELECT * FROM t1 ORDER BY c3;
#sync_slave_with_master;
connection slave;
--sleep 2
SELECT * FROM t1 ORDER BY c3;
STOP SLAVE;

View file

@ -0,0 +1,132 @@
--source include/have_ndb.inc
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
#
# Currently test only works with ndb since it retrieves "old"
# binlog positions with cluster_replication.binlog_index and apply_status;
#
# stop the save
connection slave;
STOP SLAVE;
CREATE DATABASE ndbsynctest;
USE ndbsynctest;
# get some data on the master
connection master;
CREATE DATABASE ndbsynctest;
USE ndbsynctest;
CREATE TABLE t1 (c1 BIT(1) NOT NULL, c2 BIT(1) NOT NULL, c3 CHAR(15), PRIMARY KEY(c3)) ENGINE = NDB ;
INSERT INTO t1 VALUES (1,1,"row1"),(0,1,"row2"),(1,0,"row3"),(0,0,"row4");
CREATE TABLE t2 (c1 CHAR(15), c2 BIT(1) NOT NULL, c3 BIT(1) NOT NULL, PRIMARY KEY(c1)) ENGINE = NDB ;
INSERT INTO t2 VALUES ("ABC",1,1),("BCDEF",0,1),("CD",1,0),("DEFGHIJKL",0,0);
SELECT hex(c1),hex(c2),c3 FROM t1 ORDER BY c3;
SELECT hex(c2),hex(c3),c1 FROM t2 ORDER BY c1;
# take a backup on master
--exec $NDB_MGM --no-defaults --ndb-connectstring=localhost:$NDBCLUSTER_PORT -e "start backup" >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_select_all --no-defaults --ndb-connectstring=localhost:$NDBCLUSTER_PORT -d sys -D , SYSTAB_0 | grep 520093696 > var/tmp.dat
CREATE TABLE IF NOT EXISTS cluster_replication.backup_info (id INT, backup_id INT);
DELETE FROM cluster_replication.backup_info;
LOAD DATA INFILE '../../var/tmp.dat' INTO TABLE cluster_replication.backup_info FIELDS TERMINATED BY ',';
--replace_column 1 <the_backup_id>
SELECT @the_backup_id:=backup_id FROM cluster_replication.backup_info;
let the_backup_id=`select @the_backup_id` ;
# update a row
UPDATE t1 SET c2=0 WHERE c3="row2";
SELECT hex(c1),hex(c2),c3 FROM t1 ORDER BY c3;
# restore on slave, first check that nothing is there
connection slave
# we should have no tables
SHOW TABLES;
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -b $the_backup_id -n 2 -r -e --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
#
# BUG#11960
# prior to bugfix "DROP DATABASE" would give a warning since
# the events were not created by ndb_restore
#
DROP DATABASE ndbsynctest;
CREATE DATABASE ndbsynctest;
USE ndbsynctest;
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -b $the_backup_id -n 2 -r -e --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
# continue test
SHOW TABLES;
SELECT hex(c1),hex(c2),c3 FROM t1 ORDER BY c3;
SELECT hex(c2),hex(c3),c1 FROM t2 ORDER BY c1;
#
# now setup replication to continue from last epoch
# 1. get apply_status epoch from slave
# 2. get corresponding _next_ binlog postition from master
# 3. change master on slave
# 1.
connection slave;
--replace_column 1 <the_epoch>
SELECT @the_epoch:=MAX(epoch) FROM cluster_replication.apply_status;
let $the_epoch= `select @the_epoch` ;
# 2.
connection master;
--replace_result $the_epoch <the_epoch>
--replace_column 1 <the_pos>
eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
FROM cluster_replication.binlog_index WHERE epoch > $the_epoch ORDER BY epoch ASC LIMIT 1;
let $the_pos= `SELECT @the_pos` ;
let $the_file= `SELECT @the_file` ;
# 3.
connection slave;
--replace_result $the_pos <the_pos>
eval CHANGE MASTER TO
master_log_file = '$the_file',
master_log_pos = $the_pos ;
START SLAVE;
#
#
#
connection master;
#sync_slave_with_master;
--sleep 2
connection slave;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 <Slave_IO_State> 7 <Read_Master_Log_Pos> 8 <Relay_Log_File> 9 <Relay_Log_Pos> 16 <Replicate_Ignore_Table> 22 <Exec_Master_Log_Pos> 23 <Relay_Log_Space> 33 <Seconds_Behind_Master>
SHOW SLAVE STATUS;
SELECT hex(c1),hex(c2),c3 FROM t1 ORDER BY c3;
SELECT hex(c2),hex(c3),c1 FROM t2 ORDER BY c1;
#
# Cleanup
#
connection master;
DROP DATABASE ndbsynctest;
#sync_slave_with_master;
--sleep 2
connection slave;
STOP SLAVE;
#
# Test some replication commands
#
connection master;
reset master;
# should now contain nothing
select * from cluster_replication.binlog_index;
connection slave;
reset slave;
# should now contain nothing
select * from cluster_replication.apply_status;

View file

@ -0,0 +1,4 @@
-- source include/have_ndb.inc
let $type= 'NDB' ;
let $extra_index= ;
-- source include/rpl_row_basic.inc

View file

@ -813,6 +813,8 @@ $c_p
$c_pp
$c_ev
CREATE DATABASE IF NOT EXISTS cluster_replication;
CREATE TABLE IF NOT EXISTS cluster_replication.binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;
END_OF_DATA

View file

@ -58,6 +58,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
log_event.h sql_repl.h slave.h rpl_filter.h \
rpl_injector.h \
stacktrace.h sql_sort.h sql_cache.h set_var.h \
spatial.h gstream.h client_settings.h tzfile.h \
tztime.h my_decimal.h\
@ -89,6 +90,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
slave.cc sql_repl.cc rpl_filter.cc rpl_tblmap.cc \
rpl_injector.cc \
sql_union.cc sql_derived.cc \
client.c sql_client.cc mini_client_errors.c pack.c\
stacktrace.c repl_failsafe.h repl_failsafe.cc \
@ -104,6 +106,8 @@ EXTRA_mysqld_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \
ha_innodb.h ha_berkeley.h ha_archive.h \
ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
ha_blackhole.h ha_federated.h ha_ndbcluster.h \
ha_ndbcluster_binlog.cc ha_ndbcluster_binlog.h \
ha_ndbcluster_tables.h \
ha_partition.cc ha_partition.h
mysqld_DEPENDENCIES = @mysql_se_objs@
gen_lex_hash_SOURCES = gen_lex_hash.cc
@ -160,6 +164,9 @@ ha_berkeley.o: ha_berkeley.cc ha_berkeley.h
ha_ndbcluster.o:ha_ndbcluster.cc ha_ndbcluster.h
$(CXXCOMPILE) @ndbcluster_includes@ $(LM_CFLAGS) -c $<
ha_ndbcluster_binlog.o:ha_ndbcluster_binlog.cc ha_ndbcluster_binlog.h
$(CXXCOMPILE) @ndbcluster_includes@ $(LM_CFLAGS) -c $<
#Until we can get rid of dependencies on ha_ndbcluster.h
handler.o: handler.cc ha_ndbcluster.h
$(CXXCOMPILE) @ndbcluster_includes@ $(CXXFLAGS) -c $<

View file

@ -170,6 +170,7 @@ handlerton archive_hton = {
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
NULL, /* Alter interface */
HTON_NO_FLAGS
};
@ -973,7 +974,10 @@ int ha_archive::get_row(azio_stream *file_to_read, byte *buf)
for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
ptr != end ;
ptr++)
total_blob_length += ((Field_blob*) table->field[*ptr])->get_length();
{
if (ha_get_bit_in_read_set(((Field_blob*) table->field[*ptr])->fieldnr))
total_blob_length += ((Field_blob*) table->field[*ptr])->get_length();
}
/* Adjust our row buffer if we need be */
buffer.alloc(total_blob_length);
@ -987,11 +991,18 @@ int ha_archive::get_row(azio_stream *file_to_read, byte *buf)
size_t size= ((Field_blob*) table->field[*ptr])->get_length();
if (size)
{
read= azread(file_to_read, last, size);
if ((size_t) read != size)
DBUG_RETURN(HA_ERR_END_OF_FILE);
((Field_blob*) table->field[*ptr])->set_ptr(size, last);
last += size;
if (ha_get_bit_in_read_set(((Field_blob*) table->field[*ptr])->fieldnr))
{
read= azread(file_to_read, last, size);
if ((size_t) read != size)
DBUG_RETURN(HA_ERR_END_OF_FILE);
((Field_blob*) table->field[*ptr])->set_ptr(size, last);
last += size;
}
else
{
(void)azseek(file_to_read, size, SEEK_CUR);
}
}
}
DBUG_RETURN(0);

File diff suppressed because it is too large Load diff

View file

@ -42,8 +42,10 @@ class NdbEventOperation;
// connectstring to cluster if given by mysqld
extern const char *ndbcluster_connectstring;
extern ulong ndb_cache_check_time;
#ifdef HAVE_NDB_BINLOG
extern ulong ndb_report_thresh_binlog_epoch_slip;
extern ulong ndb_report_thresh_binlog_mem_usage;
#endif
typedef enum ndb_index_type {
UNDEFINED_INDEX = 0,
@ -93,8 +95,26 @@ typedef struct st_ndbcluster_share {
ulonglong commit_count;
char *db;
char *table_name;
#ifdef HAVE_NDB_BINLOG
uint32 flags;
NDB_SHARE_STATE state;
NdbEventOperation *op;
NdbEventOperation *op_old; // for rename table
char *old_names; // for rename table
TABLE_SHARE *table_share;
TABLE *table;
NdbValue *ndb_value[2];
MY_BITMAP *subscriber_bitmap;
MY_BITMAP slock_bitmap;
uint32 slock[256/32]; // 256 bits for lock status of table
#endif
} NDB_SHARE;
#ifdef HAVE_NDB_BINLOG
/* NDB_SHARE.flags */
#define NSF_HIDDEN_PK 1 /* table has hidden primary key */
#endif
typedef enum ndb_item_type {
NDB_VALUE = 0, // Qualified more with Item::Type
NDB_FIELD = 1, // Qualified from table definition
@ -468,6 +488,11 @@ class Ndb_cond_traverse_context
Place holder for ha_ndbcluster thread specific data
*/
enum THD_NDB_OPTIONS
{
TNO_NO_LOG_SCHEMA_OP= 1 << 0
};
class Thd_ndb
{
public:
@ -479,6 +504,7 @@ class Thd_ndb
NdbTransaction *all;
NdbTransaction *stmt;
int error;
uint32 options;
List<NDB_SHARE> changed_tables;
};
@ -560,6 +586,9 @@ class ha_ndbcluster: public handler
bool low_byte_first() const;
bool has_transactions();
virtual bool is_injective() const { return true; }
const char* index_type(uint key_number);
double scan_time();
@ -791,18 +820,10 @@ private:
extern SHOW_VAR ndb_status_variables[];
bool ndbcluster_init(void);
int ndbcluster_end(ha_panic_function flag);
int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
const void** frmblob, uint* frmlen);
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir, List<char> *files);
int ndbcluster_table_exists_in_engine(THD* thd,
const char *db, const char *name);
void ndbcluster_drop_database(char* path);
void ndbcluster_print_error(int error, const NdbOperation *error_op);
bool ndbcluster_show_status(THD*,stat_print_fn *,enum ha_stat_type);

2732
sql/ha_ndbcluster_binlog.cc Normal file

File diff suppressed because it is too large Load diff

162
sql/ha_ndbcluster_binlog.h Normal file
View file

@ -0,0 +1,162 @@
/* Copyright (C) 2000-2003 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
*/
// Typedefs for long names
typedef NdbDictionary::Object NDBOBJ;
typedef NdbDictionary::Column NDBCOL;
typedef NdbDictionary::Table NDBTAB;
typedef NdbDictionary::Index NDBINDEX;
typedef NdbDictionary::Dictionary NDBDICT;
typedef NdbDictionary::Event NDBEVENT;
#define IS_TMP_PREFIX(A) (is_prefix(A, tmp_file_prefix) || is_prefix(A, "@0023sql"))
extern ulong ndb_extra_logging;
#ifdef HAVE_NDB_BINLOG
#define INJECTOR_EVENT_LEN 200
enum SCHEMA_OP_TYPE
{
SOT_DROP_TABLE,
SOT_CREATE_TABLE,
SOT_RENAME_TABLE,
SOT_ALTER_TABLE,
SOT_DROP_DB,
SOT_CREATE_DB,
SOT_ALTER_DB,
SOT_CLEAR_SLOCK
};
const uint max_ndb_nodes= 64; /* multiple of 32 */
extern pthread_t ndb_binlog_thread;
extern pthread_mutex_t injector_mutex;
extern pthread_cond_t injector_cond;
static const char *ha_ndb_ext=".ndb";
static const char share_prefix[]= "./";
extern unsigned char g_node_id_map[max_ndb_nodes];
extern handlerton ndbcluster_hton;
extern pthread_t ndb_util_thread;
extern pthread_mutex_t LOCK_ndb_util_thread;
extern pthread_cond_t COND_ndb_util_thread;
extern int ndbcluster_util_inited;
extern pthread_mutex_t ndbcluster_mutex;
extern HASH ndbcluster_open_tables;
extern Ndb_cluster_connection* g_ndb_cluster_connection;
extern long ndb_number_of_storage_nodes;
/*
Initialize the binlog part of the ndb handlerton
*/
void ndbcluster_binlog_init_handlerton();
/*
Initialize the binlog part of the NDB_SHARE
*/
void ndbcluster_binlog_init_share(NDB_SHARE *share, TABLE *table);
int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
const char *db,
const char *table_name,
NDB_SHARE *share);
int ndbcluster_create_event(Ndb *ndb, const NDBTAB *table,
const char *event_name, NDB_SHARE *share);
int ndbcluster_create_event_ops(NDB_SHARE *share,
const NDBTAB *ndbtab,
const char *event_name);
int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
const char *query, int query_length,
const char *db, const char *table_name,
uint32 ndb_table_id,
uint32 ndb_table_version,
enum SCHEMA_OP_TYPE type);
int ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
NDB_SHARE *share);
void ndb_rep_event_name(String *event_name,
const char *db, const char *tbl);
int ndbcluster_binlog_start();
pthread_handler_t ndb_binlog_thread_func(void *arg);
/*
table cluster_replication.apply_status
*/
void ndbcluster_setup_binlog_table_shares(THD *thd);
extern NDB_SHARE *apply_status_share;
extern NDB_SHARE *schema_share;
extern THD *injector_thd;
extern int ndb_binlog_thread_running;
bool
ndbcluster_show_status_binlog(THD* thd, stat_print_fn *stat_print,
enum ha_stat_type stat_type);
/*
prototypes for ndb handler utility function also needed by
the ndb binlog code
*/
int ndbcluster_find_all_files(THD *thd);
void ndb_unpack_record(TABLE *table, NdbValue *value,
MY_BITMAP *defined, byte *buf);
NDB_SHARE *ndbcluster_get_share(const char *key,
TABLE *table,
bool create_if_not_exists,
bool have_lock);
NDB_SHARE *ndbcluster_get_share(NDB_SHARE *share);
void ndbcluster_free_share(NDB_SHARE **share, bool have_lock);
void ndbcluster_real_free_share(NDB_SHARE **share);
int handle_trailing_share(NDB_SHARE *share);
inline NDB_SHARE *get_share(const char *key,
TABLE *table,
bool create_if_not_exists= TRUE,
bool have_lock= FALSE)
{
return ndbcluster_get_share(key, table, create_if_not_exists, have_lock);
}
inline NDB_SHARE *get_share(NDB_SHARE *share)
{
return ndbcluster_get_share(share);
}
inline void free_share(NDB_SHARE **share, bool have_lock= FALSE)
{
ndbcluster_free_share(share, have_lock);
}
inline void real_free_share(NDB_SHARE **share)
{
ndbcluster_real_free_share(share);
}
inline
Thd_ndb *
get_thd_ndb(THD *thd) { return (Thd_ndb *) thd->ha_data[ndbcluster_hton.slot]; }
inline
void
set_thd_ndb(THD *thd, Thd_ndb *thd_ndb) { thd->ha_data[ndbcluster_hton.slot]= thd_ndb; }
Ndb* check_ndb_in_thd(THD* thd);
#endif /* HAVE_NDB_BINLOG */

View file

@ -0,0 +1,21 @@
/* Copyright (C) 2000-2003 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
*/
#define NDB_REP_DB "cluster_replication"
#define NDB_REP_TABLE "binlog_index"
#define NDB_APPLY_TABLE "apply_status"
#define NDB_SCHEMA_TABLE "schema"

View file

@ -2425,6 +2425,132 @@ int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
DBUG_RETURN(error);
}
#ifdef HAVE_NDB_BINLOG
/*
TODO: change this into a dynamic struct
List<handlerton> does not work as
1. binlog_end is called when MEM_ROOT is gone
2. cannot work with thd MEM_ROOT as memory should be freed
*/
#define MAX_HTON_LIST_ST 63
struct hton_list_st
{
handlerton *hton[MAX_HTON_LIST_ST];
uint sz;
};
struct binlog_func_st
{
enum_binlog_func fn;
void *arg;
};
/*
Listing handlertons first to avoid recursive calls and deadlock
*/
static my_bool binlog_func_list(THD *thd, st_plugin_int *plugin, void *arg)
{
hton_list_st *hton_list= (hton_list_st *)arg;
handlerton *hton= (handlerton *) plugin->plugin->info;
if (hton->state == SHOW_OPTION_YES && hton->binlog_func)
{
uint sz= hton_list->sz;
if (sz == MAX_HTON_LIST_ST-1)
{
/* list full */
return FALSE;
}
hton_list->hton[sz]= hton;
hton_list->sz= sz+1;
}
return FALSE;
}
static my_bool binlog_func_foreach(THD *thd, binlog_func_st *bfn)
{
handlerton *hton;
hton_list_st hton_list;
hton_list.sz= 0;
plugin_foreach(thd, binlog_func_list,
MYSQL_STORAGE_ENGINE_PLUGIN, &hton_list);
uint i= 0, sz= hton_list.sz;
while(i < sz)
hton_list.hton[i++]->binlog_func(thd, bfn->fn, bfn->arg);
return FALSE;
}
int ha_reset_logs(THD *thd)
{
binlog_func_st bfn= {BFN_RESET_LOGS, 0};
binlog_func_foreach(thd, &bfn);
return 0;
}
void ha_reset_slave(THD* thd)
{
binlog_func_st bfn= {BFN_RESET_SLAVE, 0};
binlog_func_foreach(thd, &bfn);
}
void ha_binlog_wait(THD* thd)
{
binlog_func_st bfn= {BFN_BINLOG_WAIT, 0};
binlog_func_foreach(thd, &bfn);
}
int ha_binlog_end(THD* thd)
{
binlog_func_st bfn= {BFN_BINLOG_END, 0};
binlog_func_foreach(thd, &bfn);
return 0;
}
int ha_binlog_index_purge_file(THD *thd, const char *file)
{
binlog_func_st bfn= {BFN_BINLOG_PURGE_FILE, (void *)file};
binlog_func_foreach(thd, &bfn);
}
struct binlog_log_query_st
{
enum_binlog_command binlog_command;
const char *query;
uint query_length;
const char *db;
const char *table_name;
};
static my_bool binlog_log_query_handlerton(THD *thd,
st_plugin_int *plugin,
void *args)
{
struct binlog_log_query_st *b= (struct binlog_log_query_st*)args;
handlerton *hton= (handlerton *) plugin->plugin->info;
if (hton->state == SHOW_OPTION_YES && hton->binlog_log_query)
hton->binlog_log_query(thd,
b->binlog_command,
b->query,
b->query_length,
b->db,
b->table_name);
return FALSE;
}
void ha_binlog_log_query(THD *thd, enum_binlog_command binlog_command,
const char *query, uint query_length,
const char *db, const char *table_name)
{
struct binlog_log_query_st b;
b.binlog_command= binlog_command;
b.query= query;
b.query_length= query_length;
b.db= db;
b.table_name= table_name;
plugin_foreach(thd, binlog_log_query_handlerton,
MYSQL_STORAGE_ENGINE_PLUGIN, &b);
}
#endif
/*
Read the first row of a multi-range set.
@ -2846,6 +2972,8 @@ template<class RowsEventT> int binlog_log_row(TABLE* table,
const byte *before_record,
const byte *after_record)
{
if (table->file->is_injective())
return 0;
bool error= 0;
THD *const thd= current_thd;

View file

@ -216,6 +216,24 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT };
enum enum_binlog_func {
BFN_RESET_LOGS= 1,
BFN_RESET_SLAVE= 2,
BFN_BINLOG_WAIT= 3,
BFN_BINLOG_END= 4,
BFN_BINLOG_PURGE_FILE= 5
};
enum enum_binlog_command {
LOGCOM_CREATE_TABLE,
LOGCOM_ALTER_TABLE,
LOGCOM_RENAME_TABLE,
LOGCOM_DROP_TABLE,
LOGCOM_CREATE_DB,
LOGCOM_ALTER_DB,
LOGCOM_DROP_DB
};
/* struct to hold information about the table that should be created */
/* Bits in used_fields */
@ -431,7 +449,8 @@ typedef struct
handlerton structure version
*/
const int interface_version;
#define MYSQL_HANDLERTON_INTERFACE_VERSION 0x0000
/* last version change: 0x0001 in 5.1.6 */
#define MYSQL_HANDLERTON_INTERFACE_VERSION 0x0001
/*
@ -523,6 +542,15 @@ typedef struct
bool (*show_status)(THD *thd, stat_print_fn *print, enum ha_stat_type stat);
int (*alter_tablespace)(THD *thd, st_alter_tablespace *ts_info);
uint32 flags; /* global handler flags */
/*
Handlerton functions are not set in the different storage
engines static initialization. They are initialized at handler init.
Thus, leave them last in the struct.
*/
int (*binlog_func)(THD *thd, enum_binlog_func fn, void *arg);
void (*binlog_log_query)(THD *thd, enum_binlog_command binlog_command,
const char *query, uint query_length,
const char *db, const char *table_name);
} handlerton;
extern const handlerton default_hton;
@ -1205,6 +1233,12 @@ public:
virtual int ha_write_row(byte * buf);
virtual int ha_update_row(const byte * old_data, byte * new_data);
virtual int ha_delete_row(const byte * buf);
/*
If the handler does it's own injection of the rows, this member function
should return 'true'.
*/
virtual bool is_injective() const { return false; }
/*
SYNOPSIS
start_bulk_update()
@ -1718,3 +1752,21 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht);
int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
my_off_t end_offset);
int ha_repl_report_replication_stop(THD *thd);
#ifdef HAVE_NDB_BINLOG
int ha_reset_logs(THD *thd);
int ha_binlog_index_purge_file(THD *thd, const char *file);
void ha_reset_slave(THD *thd);
void ha_binlog_log_query(THD *thd, enum_binlog_command binlog_command,
const char *query, uint query_length,
const char *db, const char *table_name);
void ha_binlog_wait(THD *thd);
int ha_binlog_end(THD *thd);
#else
#define ha_reset_logs(a) 0
#define ha_binlog_index_purge_file(a,b) 0
#define ha_reset_slave(a)
#define ha_binlog_log_query(a,b,c,d,e,f);
#define ha_binlog_wait(a)
#define ha_binlog_end(a) 0
#endif

View file

@ -988,6 +988,7 @@ bool MYSQL_LOG::reset_logs(THD* thd)
enum_log_type save_log_type;
DBUG_ENTER("reset_logs");
ha_reset_logs(thd);
/*
We need to get both locks to be sure that no one is trying to
write to the index log file.
@ -1237,6 +1238,9 @@ int MYSQL_LOG::purge_logs(const char *to_log,
DBUG_PRINT("info",("purging %s",log_info.log_file_name));
if (!my_delete(log_info.log_file_name, MYF(0)) && decrease_log_space)
*decrease_log_space-= file_size;
ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
if (find_next_log(&log_info, 0) || exit_loop)
break;
}
@ -1297,6 +1301,9 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time)
stat_area.st_mtime >= purge_time)
break;
my_delete(log_info.log_file_name, MYF(0));
ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
if (find_next_log(&log_info, 0))
break;
}

View file

@ -79,6 +79,20 @@ static void clear_all_errors(THD *thd, struct st_relay_log_info *rli)
inline int ignored_error_code(int err_code)
{
#ifdef HAVE_NDB_BINLOG
/*
The following error codes are hard-coded and will always be ignored.
*/
switch (err_code)
{
case ER_DB_CREATE_EXISTS:
case ER_DB_DROP_EXISTS:
return 1;
default:
/* Nothing to do */
break;
}
#endif
return ((err_code == ER_SLAVE_IGNORED_TABLE) ||
(use_slave_mask && bitmap_is_set(&slave_error_mask, err_code)));
}
@ -5276,7 +5290,8 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
{
slave_print_msg(ERROR_LEVEL, rli, error,
"Error in %s event: error during table %s.%s lock",
get_type_str(), table->s->db, table->s->table_name);
get_type_str(), table->s->db.str,
table->s->table_name.str);
DBUG_RETURN(error);
}
/*
@ -5412,7 +5427,12 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
if (error)
{ /* error has occured during the transaction */
/*
slave_print_msg(ERROR_LEVEL, rli, error,
"Error in %s event: error during transaction execution "
"on table %s.%s",
get_type_str(), table->s->db.str,
table->s->table_name.str);
/*
If one day we honour --skip-slave-errors in row-based replication, and
the error should be skipped, then we would clear mappings, rollback,
close tables, but the slave SQL thread would not stop and then may
@ -5485,7 +5505,8 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
slave_print_msg(ERROR_LEVEL, rli, error,
"Error in %s event: commit of row events failed, "
"table `%s`.`%s`",
get_type_str(), table->s->db, table->s->table_name);
get_type_str(), table->s->db.str,
table->s->table_name.str);
DBUG_RETURN(error);
}
@ -5585,8 +5606,8 @@ void Rows_log_event::pack_info(Protocol *protocol)
{
char buf[256];
char const *const flagstr= get_flags(STMT_END_F) ? "STMT_END_F" : "";
char const *const dbnam= m_table->s->db;
char const *const tblnam= m_table->s->table_name;
char const *const dbnam= m_table->s->db.str;
char const *const tblnam= m_table->s->table_name.str;
my_size_t bytes= snprintf(buf, sizeof(buf),
"%s.%s - %s", dbnam, tblnam, flagstr);
protocol->store(buf, bytes, &my_charset_bin);
@ -6105,7 +6126,8 @@ int Write_rows_log_event::do_before_row_operations(TABLE *table)
*/
thd->lex->sql_command= SQLCOM_REPLACE;
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); // needed for ndbcluster
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); // Needed for ndbcluster
table->file->extra(HA_EXTRA_IGNORE_NO_KEY); // Needed for ndbcluster
/*
TODO: the cluster team (Tomas?) says that it's better if the engine knows
how many rows are going to be inserted, then it can allocate needed memory
@ -6373,6 +6395,9 @@ static int find_and_fetch_row(TABLE *table, byte *key, byte *record_buf)
DBUG_ASSERT(record_buf);
/* We need to retrieve all fields */
table->file->ha_set_all_bits_in_read_set();
if (table->s->keys > 0)
{
int error;

View file

@ -538,6 +538,7 @@ enum enum_mysql_completiontype {
COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6
};
bool begin_trans(THD *thd);
int end_trans(THD *thd, enum enum_mysql_completiontype completion);
Item *negate_expression(THD *thd, Item *expr);
@ -640,6 +641,7 @@ bool table_cache_init(void);
void table_cache_free(void);
bool table_def_init(void);
void table_def_free(void);
void assign_new_table_id(TABLE *table);
uint cached_open_tables(void);
uint cached_table_definitions(void);
void kill_mysql(void);
@ -1041,7 +1043,7 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
bool remove_table_from_cache(THD *thd, const char *db, const char *table,
uint flags);
bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables);
bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables, bool have_lock = FALSE);
void copy_field_from_tmp_record(Field *field,int offset);
bool fill_record(THD *thd, Field **field, List<Item> &values,
bool ignore_errors);

View file

@ -417,6 +417,11 @@ my_bool opt_ndb_shm, opt_ndb_optimized_node_selection;
ulong opt_ndb_cache_check_time;
const char *opt_ndb_mgmd;
ulong opt_ndb_nodeid;
ulong ndb_extra_logging;
#ifdef HAVE_NDB_BINLOG
ulong ndb_report_thresh_binlog_epoch_slip;
ulong ndb_report_thresh_binlog_mem_usage;
#endif
extern SHOW_VAR ndb_status_variables[];
extern const char *ndb_distribution_names[];
@ -1134,6 +1139,11 @@ void clean_up(bool print_message)
mysql_log.cleanup();
mysql_slow_log.cleanup();
/*
make sure that handlers finish up
what they have that is dependent on the binlog
*/
ha_binlog_end(current_thd);
mysql_bin_log.cleanup();
#ifdef HAVE_REPLICATION
@ -3106,11 +3116,12 @@ with --log-bin instead.");
}
if (opt_binlog_format_id == BF_UNSPECIFIED)
{
/*
We use statement-based by default, but could change this to be row-based
if this is a cluster build (i.e. have_ndbcluster is true)...
*/
opt_binlog_format_id= BF_STMT;
#ifdef HAVE_NDB_BINLOG
if (have_ndbcluster == SHOW_OPTION_YES)
opt_binlog_format_id= BF_ROW;
else
#endif
opt_binlog_format_id= BF_STMT;
}
#ifdef HAVE_ROW_BASED_REPLICATION
if (opt_binlog_format_id == BF_ROW)
@ -4646,6 +4657,9 @@ enum options_mysqld
OPT_NDB_DISTRIBUTION,
OPT_NDB_INDEX_STAT_ENABLE,
OPT_NDB_INDEX_STAT_CACHE_ENTRIES, OPT_NDB_INDEX_STAT_UPDATE_FREQ,
OPT_NDB_EXTRA_LOGGING,
OPT_NDB_REPORT_THRESH_BINLOG_EPOCH_SLIP,
OPT_NDB_REPORT_THRESH_BINLOG_MEM_USAGE,
OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
@ -4848,7 +4862,11 @@ Disable with --skip-bdb (will save memory).",
"Tell the master the form of binary logging to use: either 'row' for "
"row-based binary logging (which automatically turns on "
"innodb_locks_unsafe_for_binlog as it is safe in this case), or "
"'statement' for statement-based logging. ",
"'statement' for statement-based logging. "
#ifdef HAVE_NDB_BINLOG
"If ndbcluster is enabled, the default will be set to 'row'."
#endif
,
#else
"Tell the master the form of binary logging to use: this release build "
"supports only statement-based binary logging, so only 'statement' is "
@ -5302,6 +5320,29 @@ Disable with --skip-ndbcluster (will save memory).",
(gptr*) &global_system_variables.ndb_force_send,
(gptr*) &global_system_variables.ndb_force_send,
0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
{"ndb-extra-logging", OPT_NDB_EXTRA_LOGGING,
"Turn on more logging in the error log.",
(gptr*) &ndb_extra_logging,
(gptr*) &ndb_extra_logging,
0, GET_INT, OPT_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_NDB_BINLOG
{"ndb-report-thresh-binlog-epoch-slip", OPT_NDB_REPORT_THRESH_BINLOG_EPOCH_SLIP,
"Threshold on number of epochs to be behind before reporting binlog status. "
"E.g. 3 means that if the difference between what epoch has been received "
"from the storage nodes and what has been applied to the binlog is 3 or more, "
"a status message will be sent to the cluster log.",
(gptr*) &ndb_report_thresh_binlog_epoch_slip,
(gptr*) &ndb_report_thresh_binlog_epoch_slip,
0, GET_ULONG, REQUIRED_ARG, 3, 0, 256, 0, 0, 0},
{"ndb-report-thresh-binlog-mem-usage", OPT_NDB_REPORT_THRESH_BINLOG_MEM_USAGE,
"Threshold on percentage of free memory before reporting binlog status. E.g. "
"10 means that if amount of available memory for receiving binlog data from "
"the storage nodes goes below 10%, "
"a status message will be sent to the cluster log.",
(gptr*) &ndb_report_thresh_binlog_mem_usage,
(gptr*) &ndb_report_thresh_binlog_mem_usage,
0, GET_ULONG, REQUIRED_ARG, 10, 0, 100, 0, 0, 0},
#endif
{"ndb-use-exact-count", OPT_NDB_USE_EXACT_COUNT,
"Use exact records count during query planning and for fast "
"select count(*), disable for faster queries.",
@ -7500,6 +7541,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
opt_ndb_distribution_id= (enum ndb_distribution)(id-1);
break;
case OPT_NDB_EXTRA_LOGGING:
if (!argument)
ndb_extra_logging++;
else if (argument == disabled_my_option)
ndb_extra_logging= 0L;
else
ndb_extra_logging= atoi(argument);
break;
#endif
case OPT_INNODB:
#ifdef WITH_INNOBASE_STORAGE_ENGINE
@ -8056,6 +8105,7 @@ ulong srv_commit_concurrency;
#ifndef WITH_NDBCLUSTER_STORAGE_ENGINE
ulong ndb_cache_check_time;
ulong ndb_extra_logging;
#endif
/*****************************************************************************

153
sql/rpl_injector.cc Normal file
View file

@ -0,0 +1,153 @@
/*
Copyright (C) 2005 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */
#include "mysql_priv.h"
#include "rpl_injector.h"
#ifdef HAVE_ROW_BASED_REPLICATION
/*
injector::transaction - member definitions
*/
/* inline since it's called below */
inline
injector::transaction::transaction(MYSQL_LOG *log, THD *thd)
: m_thd(thd)
{
/*
Default initialization of m_start_pos (which initializes it to garbage).
We need to fill it in using the code below.
*/
LOG_INFO log_info;
log->get_current_log(&log_info);
/* !!! binlog_pos does not follow RAII !!! */
m_start_pos.m_file_name= my_strdup(log_info.log_file_name, MYF(0));
m_start_pos.m_file_pos= log_info.pos;
begin_trans(m_thd);
}
injector::transaction::~transaction()
{
/* Needed since my_free expects a 'char*' (instead of 'void*'). */
char* const the_memory= const_cast<char*>(m_start_pos.m_file_name);
/*
We set the first character to null just to give all the copies of the
start position a (minimal) chance of seening that the memory is lost.
All assuming the my_free does not step over the memory, of course.
*/
*the_memory= '\0';
my_free(the_memory, MYF(0));
}
int injector::transaction::commit()
{
DBUG_ENTER("injector::transaction::commit()");
m_thd->binlog_flush_pending_rows_event(true);
end_trans(m_thd, COMMIT);
DBUG_RETURN(0);
}
int injector::transaction::write_row (server_id_type sid, table tbl,
MY_BITMAP const* cols, size_t colcnt,
record_type record)
{
DBUG_ENTER("injector::transaction::write_row(...)");
m_thd->set_server_id(sid);
m_thd->binlog_write_row(tbl.get_table(), tbl.is_transactional(),
cols, colcnt, record);
DBUG_RETURN(0);
}
int injector::transaction::delete_row(server_id_type sid, table tbl,
MY_BITMAP const* cols, size_t colcnt,
record_type record)
{
DBUG_ENTER("injector::transaction::delete_row(...)");
m_thd->set_server_id(sid);
m_thd->binlog_delete_row(tbl.get_table(), tbl.is_transactional(),
cols, colcnt, record);
DBUG_RETURN(0);
}
int injector::transaction::update_row(server_id_type sid, table tbl,
MY_BITMAP const* cols, size_t colcnt,
record_type before, record_type after)
{
DBUG_ENTER("injector::transaction::update_row(...)");
m_thd->set_server_id(sid);
m_thd->binlog_update_row(tbl.get_table(), tbl.is_transactional(),
cols, colcnt, before, after);
DBUG_RETURN(0);
}
injector::transaction::binlog_pos injector::transaction::start_pos() const
{
return m_start_pos;
}
/*
injector - member definitions
*/
/* This constructor is called below */
inline injector::injector()
{
}
static injector *s_injector= 0;
injector *injector::instance()
{
if (s_injector == 0)
s_injector= new injector;
/* "There can be only one [instance]" */
return s_injector;
}
injector::transaction injector::new_trans(THD *thd)
{
DBUG_ENTER("injector::new_trans(THD*)");
/*
Currently, there is no alternative to using 'mysql_bin_log' since that
is hardcoded into the way the handler is using the binary log.
*/
DBUG_RETURN(transaction(&mysql_bin_log, thd));
}
void injector::new_trans(THD *thd, injector::transaction *ptr)
{
DBUG_ENTER("injector::new_trans(THD *, transaction *)");
/*
Currently, there is no alternative to using 'mysql_bin_log' since that
is hardcoded into the way the handler is using the binary log.
*/
transaction trans(&mysql_bin_log, thd);
ptr->swap(trans);
DBUG_VOID_RETURN;
}
#endif

251
sql/rpl_injector.h Normal file
View file

@ -0,0 +1,251 @@
/*
Copyright (C) 2005 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */
#ifndef INJECTOR_H
#define INJECTOR_H
/* Pull in 'byte', 'my_off_t', and 'uint32' */
#include <my_global.h>
#ifdef HAVE_ROW_BASED_REPLICATION
#include <my_bitmap.h>
/* Forward declarations */
class handler;
class MYSQL_LOG;
class st_table;
typedef st_table TABLE;
/*
Injector to inject rows into the MySQL server.
The injector class is used to notify the MySQL server of new rows that have
appeared outside of MySQL control.
The original purpose of this is to allow clusters---which handle replication
inside the cluster through other means---to insert new rows into binary log.
Note, however, that the injector should be used whenever rows are altered in
any manner that is outside of MySQL server visibility and which therefore
are not seen by the MySQL server.
*/
class injector
{
public:
/*
Get an instance of the injector.
DESCRIPTION
The injector is a Singleton, so this static function return the
available instance of the injector.
RETURN VALUE
A pointer to the available injector object.
*/
static injector *instance();
/*
A transaction where rows can be added.
DESCRIPTION
The transaction class satisfy the **CopyConstructible** and
**Assignable** requirements. Note that the transaction is *not*
default constructible.
*/
class transaction {
friend class injector;
public:
/* Convenience definitions */
typedef byte* record_type;
typedef uint32 server_id_type;
/*
Table reference.
RESPONSIBILITY
The class contains constructors to handle several forms of
references to tables. The constructors can implicitly be used to
construct references from, e.g., strings containing table names.
EXAMPLE
The class is intended to be used *by value*. Please, do not try to
construct objects of this type using 'new'; instead construct an
object, possibly a temporary object. For example:
injector::transaction::table tbl(share->table, true);
MY_BITMAP cols;
bitmap_init(&cols, NULL, (i + 7) / 8, false);
inj->write_row(::server_id, tbl, &cols, row_data);
or
MY_BITMAP cols;
bitmap_init(&cols, NULL, (i + 7) / 8, false);
inj->write_row(::server_id,
injector::transaction::table(share->table, true),
&cols, row_data);
This will work, be more efficient, and have greater chance of
inlining, not run the risk of losing pointers.
COLLABORATION
injector::transaction
Provide a flexible interface to the representation of tables.
*/
class table
{
public:
table(TABLE *table, bool is_transactional)
: m_table(table), m_is_transactional(is_transactional)
{
}
char const *db_name() const { return m_table->s->db.str; }
char const *table_name() const { return m_table->s->table_name.str; }
TABLE *get_table() const { return m_table; }
bool is_transactional() const { return m_is_transactional; }
private:
TABLE *m_table;
bool m_is_transactional;
};
/*
Binlog position as a structure.
*/
class binlog_pos {
friend class transaction;
public:
char const *file_name() const { return m_file_name; }
my_off_t file_pos() const { return m_file_pos; }
private:
char const *m_file_name;
my_off_t m_file_pos;
};
transaction() : m_thd(NULL) { }
transaction(transaction const&);
~transaction();
/* Clear transaction, i.e., make calls to 'good()' return false. */
void clear() { m_thd= NULL; }
/* Is the transaction in a good state? */
bool good() const { return m_thd != NULL; }
/* Default assignment operator: standard implementation */
transaction& operator=(transaction t) {
swap(t);
return *this;
}
/*
Add a 'write row' entry to the transaction.
*/
int write_row (server_id_type sid, table tbl,
MY_BITMAP const *cols, size_t colcnt,
record_type record);
/*
Add a 'delete row' entry to the transaction.
*/
int delete_row(server_id_type sid, table tbl,
MY_BITMAP const *cols, size_t colcnt,
record_type record);
/*
Add an 'update row' entry to the transaction.
*/
int update_row(server_id_type sid, table tbl,
MY_BITMAP const *cols, size_t colcnt,
record_type before, record_type after);
/*
Commit a transaction.
This member function will clean up after a sequence of *_row calls by,
for example, releasing resource and unlocking files.
*/
int commit();
/*
Get the position for the start of the transaction.
Returns the position in the binary log of the first event in this
transaction. If no event is yet written, the position where the event
*will* be written is returned. This position is known, since a
new_transaction() will lock the binary log and prevent any other
writes to the binary log.
*/
binlog_pos start_pos() const;
private:
/* Only the injector may construct these object */
transaction(MYSQL_LOG *, THD *);
void swap(transaction& o) {
/* std::swap(m_start_pos, o.m_start_pos); */
{
binlog_pos const tmp= m_start_pos;
m_start_pos= o.m_start_pos;
o.m_start_pos= tmp;
}
/* std::swap(m_thd, o.m_thd); */
{
THD* const tmp= m_thd;
m_thd= o.m_thd;
o.m_thd= tmp;
}
}
binlog_pos m_start_pos;
THD *m_thd;
};
/*
Create a new transaction. This member function will prepare for a
sequence of *_row calls by, for example, reserving resources and
locking files. There are two overloaded alternatives: one returning a
transaction by value and one using placement semantics. The following
two calls are equivalent, with the exception that the latter will
overwrite the transaction.
injector::transaction trans1= inj->new_trans(thd);
injector::transaction trans2;
inj->new_trans(thd, &trans);
*/
transaction new_trans(THD *);
void new_trans(THD *, transaction *);
private:
explicit injector();
~injector() { } /* Nothing needs to be done */
injector(injector const&); /* You're not allowed to copy injector
instances.
*/
};
#endif /* HAVE_ROW_BASED_REPLICATION */
#endif /* INJECTOR_H */

View file

@ -101,6 +101,11 @@ extern ulong srv_commit_concurrency;
/* WITH_NDBCLUSTER_STORAGE_ENGINE */
extern ulong ndb_cache_check_time;
extern ulong ndb_extra_logging;
#ifdef HAVE_NDB_BINLOG
extern ulong ndb_report_thresh_binlog_epoch_slip;
extern ulong ndb_report_thresh_binlog_mem_usage;
#endif
@ -481,6 +486,14 @@ sys_ndb_autoincrement_prefetch_sz("ndb_autoincrement_prefetch_sz",
&SV::ndb_autoincrement_prefetch_sz);
sys_var_thd_bool
sys_ndb_force_send("ndb_force_send", &SV::ndb_force_send);
#ifdef HAVE_NDB_BINLOG
sys_var_long_ptr
sys_ndb_report_thresh_binlog_epoch_slip("ndb_report_thresh_binlog_epoch_slip",
&ndb_report_thresh_binlog_epoch_slip);
sys_var_long_ptr
sys_ndb_report_thresh_binlog_mem_usage("ndb_report_thresh_binlog_mem_usage",
&ndb_report_thresh_binlog_mem_usage);
#endif
sys_var_thd_bool
sys_ndb_use_exact_count("ndb_use_exact_count", &SV::ndb_use_exact_count);
sys_var_thd_bool
@ -496,6 +509,8 @@ sys_ndb_index_stat_cache_entries("ndb_index_stat_cache_entries",
sys_var_thd_ulong
sys_ndb_index_stat_update_freq("ndb_index_stat_update_freq",
&SV::ndb_index_stat_update_freq);
sys_var_long_ptr
sys_ndb_extra_logging("ndb_extra_logging", &ndb_extra_logging);
/* Time/date/datetime formats */
@ -847,10 +862,17 @@ SHOW_VAR init_vars[]= {
{sys_ndb_autoincrement_prefetch_sz.name,
(char*) &sys_ndb_autoincrement_prefetch_sz, SHOW_SYS},
{sys_ndb_cache_check_time.name,(char*) &sys_ndb_cache_check_time, SHOW_SYS},
{sys_ndb_extra_logging.name,(char*) &sys_ndb_extra_logging, SHOW_SYS},
{sys_ndb_force_send.name, (char*) &sys_ndb_force_send, SHOW_SYS},
{sys_ndb_index_stat_cache_entries.name, (char*) &sys_ndb_index_stat_cache_entries, SHOW_SYS},
{sys_ndb_index_stat_enable.name, (char*) &sys_ndb_index_stat_enable, SHOW_SYS},
{sys_ndb_index_stat_update_freq.name, (char*) &sys_ndb_index_stat_update_freq, SHOW_SYS},
#ifdef HAVE_NDB_BINLOG
{sys_ndb_report_thresh_binlog_epoch_slip.name,
(char*) &sys_ndb_report_thresh_binlog_epoch_slip, SHOW_SYS},
{sys_ndb_report_thresh_binlog_mem_usage.name,
(char*) &sys_ndb_report_thresh_binlog_mem_usage, SHOW_SYS},
#endif
{sys_ndb_use_exact_count.name,(char*) &sys_ndb_use_exact_count, SHOW_SYS},
{sys_ndb_use_transactions.name,(char*) &sys_ndb_use_transactions, SHOW_SYS},
{sys_net_buffer_length.name,(char*) &sys_net_buffer_length, SHOW_SYS},

View file

@ -39,7 +39,7 @@ typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
volatile bool slave_sql_running = 0, slave_io_running = 0;
char* slave_load_tmpdir = 0;
MASTER_INFO *active_mi;
MASTER_INFO *active_mi= 0;
my_bool replicate_same_server_id;
ulonglong relay_log_space_limit = 0;
@ -2885,6 +2885,47 @@ bool st_relay_log_info::cached_charset_compare(char *charset)
return 0;
}
/*
Check if the current error is of temporary nature of not.
Some errors are temporary in nature, such as
ER_LOCK_DEADLOCK and ER_LOCK_WAIT_TIMEOUT. Ndb also signals
that the error is temporary by pushing a warning with the error code
ER_GET_TEMPORARY_ERRMSG, if the originating error is temporary.
*/
static int has_temporary_error(THD *thd)
{
if (thd->is_fatal_error)
return 0;
/*
Temporary error codes:
currently, InnoDB deadlock detected by InnoDB or lock
wait timeout (innodb_lock_wait_timeout exceeded
*/
if (thd->net.last_errno == ER_LOCK_DEADLOCK ||
thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT)
return 1;
#ifdef HAVE_NDB_BINLOG
/*
currently temporary error set in ndbcluster
*/
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
MYSQL_ERROR *err;
while ((err= it++))
{
DBUG_PRINT("info", ("has warning %d %s", err->code, err->msg))
switch (err->code)
{
case ER_GET_TEMPORARY_ERRMSG:
return 1;
default:
break;
}
}
#endif
return 0;
}
static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
{
@ -3004,6 +3045,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
ev->when = time(NULL);
ev->thd = thd; // because up to this point, ev->thd == 0
exec_res = ev->exec_event(rli);
DBUG_PRINT("info", ("exec_event result = %d", exec_res));
DBUG_ASSERT(rli->sql_thd==thd);
/*
Format_description_log_event should not be deleted because it will be
@ -3017,17 +3059,13 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
}
if (slave_trans_retries)
{
if (exec_res &&
(thd->net.last_errno == ER_LOCK_DEADLOCK ||
thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT) &&
!thd->is_fatal_error)
if (exec_res && has_temporary_error(thd))
{
const char *errmsg;
/*
We were in a transaction which has been rolled back because of a
deadlock (currently, InnoDB deadlock detected by InnoDB) or lock
wait timeout (innodb_lock_wait_timeout exceeded); let's seek back to
BEGIN log event and retry it all again.
temporary error;
let's seek back to BEGIN log event and retry it all again.
We have to not only seek but also
a) init_master_info(), to seek back to hot relay log's start for later
(for when we will come back to this hot log after re-processing the
@ -3539,10 +3577,39 @@ Slave SQL thread aborted. Can't execute init_slave query");
{
// do not scare the user if SQL thread was simply killed or stopped
if (!sql_slave_killed(thd,rli))
{
/*
retrieve as much info as possible from the thd and, error codes and warnings
and print this to the error log as to allow the user to locate the error
*/
if (thd->net.last_errno != 0)
{
if (rli->last_slave_errno == 0)
{
slave_print_msg(ERROR_LEVEL, rli, thd->net.last_errno,
thd->net.last_error ?
thd->net.last_error : "<no message>");
}
else if (rli->last_slave_errno != thd->net.last_errno)
{
sql_print_error("Slave (additional info): %s Error_code: %d",
thd->net.last_error ?
thd->net.last_error : "<no message>",
thd->net.last_errno);
}
}
/* Print any warnings issued */
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
MYSQL_ERROR *err;
while ((err= it++))
sql_print_warning("Slave: %s Error_code: %d",err->msg, err->code);
sql_print_error("\
Error running query, slave SQL thread aborted. Fix the problem, and restart \
the slave SQL thread with \"SLAVE START\". We stopped at log \
'%s' position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff));
}
goto err;
}
}

View file

@ -803,13 +803,14 @@ void free_io_cache(TABLE *table)
*/
bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
TABLE_LIST *tables)
TABLE_LIST *tables, bool have_lock)
{
bool result=0;
DBUG_ENTER("close_cached_tables");
DBUG_ASSERT(thd || (!if_wait_for_refresh && !tables));
VOID(pthread_mutex_lock(&LOCK_open));
if (!have_lock)
VOID(pthread_mutex_lock(&LOCK_open));
if (!tables)
{
refresh_version++; // Force close of open tables
@ -888,7 +889,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
for (TABLE *table=thd->open_tables; table ; table= table->next)
table->s->version= refresh_version;
}
VOID(pthread_mutex_unlock(&LOCK_open));
if (!have_lock)
VOID(pthread_mutex_unlock(&LOCK_open));
if (if_wait_for_refresh)
{
pthread_mutex_lock(&thd->mysys_var->mutex);
@ -2383,7 +2385,7 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
table->s->table_map_id is not ULONG_MAX.
*/
static void assign_new_table_id(TABLE *table)
void assign_new_table_id(TABLE *table)
{
static ulong last_table_id= ULONG_MAX;

View file

@ -1383,6 +1383,7 @@ public:
#define SYSTEM_THREAD_DELAYED_INSERT 1
#define SYSTEM_THREAD_SLAVE_IO 2
#define SYSTEM_THREAD_SLAVE_SQL 4
#define SYSTEM_THREAD_NDBCLUSTER_BINLOG 8
/*
Used to hold information about file and file structure in exchainge

View file

@ -401,6 +401,7 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
bool silent)
{
char path[FN_REFLEN+16];
char tmp_query[FN_REFLEN+16];
long result= 1;
int error= 0;
MY_STAT stat_info;
@ -486,15 +487,20 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
if (!thd->query) // Only in replication
{
query= path;
query_length= (uint) (strxmov(path,"create database `", db, "`", NullS) -
path);
query= tmp_query;
query_length= (uint) (strxmov(tmp_query,"create database `",
db, "`", NullS) - tmp_query);
}
else
{
query= thd->query;
query_length= thd->query_length;
}
ha_binlog_log_query(thd, LOGCOM_CREATE_DB,
query, query_length,
db, "");
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, query, query_length, 0,
@ -569,6 +575,10 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
thd->variables.collation_database= thd->db_charset;
}
ha_binlog_log_query(thd, LOGCOM_ALTER_DB,
thd->query, thd->query_length,
db, "");
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length, 0,

View file

@ -79,7 +79,7 @@ const char *command_name[]={
"Connect","Kill","Debug","Ping","Time","Delayed insert","Change user",
"Binlog Dump","Table Dump", "Connect Out", "Register Slave",
"Prepare", "Execute", "Long Data", "Close stmt",
"Reset stmt", "Set option", "Fetch",
"Reset stmt", "Set option", "Fetch", "Daemon",
"Error" // Last command number
};
@ -149,7 +149,7 @@ static bool end_active_trans(THD *thd)
DBUG_RETURN(error);
}
static bool begin_trans(THD *thd)
bool begin_trans(THD *thd)
{
int error=0;
if (unlikely(thd->in_sub_stmt))
@ -6682,6 +6682,8 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
if (tmp->command == COM_DAEMON)
continue;
if (tmp->thread_id == id)
{
pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete

View file

@ -972,6 +972,9 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
error=1;
goto err;
}
ha_reset_slave(thd);
// delete relay logs, clear relay log coordinates
if ((error= purge_relay_logs(&mi->rli, thd,
1 /* just reset */,
@ -1316,6 +1319,13 @@ bool mysql_show_binlog_events(THD* thd)
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
/*
Wait for handlers to insert any pending information
into the binlog. For e.g. ndb which updates the binlog asynchronously
this is needed so that the uses sees all its own commands in the binlog
*/
ha_binlog_wait(thd);
if (mysql_bin_log.is_open())
{
LEX_MASTER_INFO *lex_mi= &thd->lex->mi;

View file

@ -98,32 +98,11 @@ public:
NoError = 0,
Undefined = 1,
NF_FakeErrorREF = 11,
Busy = 701
};
#if 0
enum ErrorCode {
NoError = 0,
Undefined = 1,
UndefinedTCError = 2,
NF_FakeErrorREF = 11,
Busy = 701,
NotMaster = 702,
SeizeError = 703,
EventNotFound = 4710,
EventNameTooLong = 4241,
TooManyEvents = 4242,
BadRequestType = 4247,
InvalidName = 4248,
InvalidPrimaryTable = 4249,
InvalidEventType = 4250,
NotUnique = 4251,
AllocationError = 4252,
CreateEventTableFailed = 4253,
InvalidAttributeOrder = 4255,
Temporary = 0x1 << 16
NotMaster = 702
};
#endif
STATIC_CONST( SignalLength = 5 );
STATIC_CONST( SignalLength = 7 );
STATIC_CONST( SignalLength2 = SignalLength+1 );
union { // user block reference
Uint32 senderRef;
@ -139,16 +118,8 @@ public:
};
Uint32 m_errorLine;
Uint32 m_errorNode;
#if 0
bool isTemporary() const
{ return (errorCode & Temporary) > 0; }
void setTemporary()
{ errorCode |= Temporary; }
ErrorCode setTemporary(ErrorCode ec)
{ return (ErrorCode) (errorCode = ((Uint32) ec | (Uint32)Temporary)); }
#endif
// with SignalLength2
Uint32 m_masterNodeId;
Uint32 getUserRef() const {
return m_userRef;
}
@ -179,6 +150,12 @@ public:
void setErrorNode(Uint32 val) {
m_errorNode = val;
}
Uint32 getMasterNode() const {
return m_masterNodeId;
}
void setMasterNode(Uint32 val) {
m_masterNodeId = val;
}
};
/**
@ -199,6 +176,11 @@ struct CreateEvntReq {
// RT_DICT_ABORT = 0xF << 4,
// RT_TC = 5 << 8
};
enum EventFlags {
EF_REPORT_ALL = 0x1 << 16,
EF_REPORT_SUBSCRIBE = 0x2 << 16,
EF_ALL = 0xFFFF << 16
};
STATIC_CONST( SignalLengthGet = 3 );
STATIC_CONST( SignalLengthCreate = 6+MAXNROFATTRIBUTESINWORDS );
STATIC_CONST( SignalLength = 8+MAXNROFATTRIBUTESINWORDS );
@ -217,10 +199,9 @@ struct CreateEvntReq {
Uint32 m_tableId; // table to event
Uint32 m_tableVersion; // table version
AttributeMask::Data m_attrListBitmask;
Uint32 m_eventType; // from DictTabInfo::TableType
Uint32 m_eventType; // EventFlags (16 bits) + from DictTabInfo::TableType (16 bits)
Uint32 m_eventId; // event table id set by DICT/SUMA
Uint32 m_eventKey; // event table key set by DICT/SUMA
Uint32 getUserRef() const {
return m_userRef;
}
@ -268,10 +249,10 @@ struct CreateEvntReq {
AttributeMask::assign(m_attrListBitmask.data, val);
}
Uint32 getEventType() const {
return m_eventType;
return m_eventType & ~EF_ALL;
}
void setEventType(Uint32 val) {
m_eventType = (Uint32)val;
m_eventType = (m_eventType & EF_ALL) | (~EF_ALL & (Uint32)val);
}
Uint32 getEventId() const {
return m_eventId;
@ -285,6 +266,27 @@ struct CreateEvntReq {
void setEventKey(Uint32 val) {
m_eventKey = val;
}
void clearFlags() {
m_eventType&= ~EF_ALL;
}
Uint32 getReportFlags() const {
return m_eventType & EF_ALL;
}
void setReportFlags(Uint32 val) {
m_eventType = (val & EF_ALL) | (m_eventType & ~EF_ALL);
}
Uint32 getReportAll() const {
return m_eventType & EF_REPORT_ALL ;
}
void setReportAll() {
m_eventType|= EF_REPORT_ALL;
}
Uint32 getReportSubscribe() const {
return m_eventType & EF_REPORT_SUBSCRIBE ;
}
void setReportSubscribe() {
m_eventType|= EF_REPORT_SUBSCRIBE;
}
};
/**
@ -377,42 +379,14 @@ struct CreateEvntRef {
friend bool printCREATE_EVNT_REF(FILE*, const Uint32*, Uint32, Uint16);
STATIC_CONST( SignalLength = 11 );
STATIC_CONST( SignalLength2 = SignalLength + 1 );
enum ErrorCode {
NoError = 0,
Undefined = 1,
NF_FakeErrorREF = 11,
Busy = 701
};
#if 0
enum ErrorCode {
NoError = 0,
Undefined = 1,
UndefinedTCError = 2,
NF_FakeErrorREF = 11,
Busy = 701,
NotMaster = 702,
SeizeError = 703,
TooManyEvents = 4707,
EventNameTooLong = 4708,
EventNameExists = 746,
EventNotFound = 4731,
AttributeNullable = 4246,
BadRequestType = 4247,
InvalidName = 4248,
InvalidPrimaryTable = 4249,
InvalidEventType = 4250,
NotUnique = 4251,
AllocationError = 4252,
CreateEventTableFailed = 4711,
InvalidAttributeOrder = 4255,
Temporary = 0x1 << 16
NotMaster = 702
};
bool isTemporary() const;
void setTemporary();
ErrorCode setTemporary(ErrorCode ec);
static ErrorCode makeTemporary(ErrorCode ec);
#endif
union {
Uint32 m_userRef; // user block reference
Uint32 senderRef; // user block reference
@ -431,15 +405,8 @@ struct CreateEvntRef {
Uint32 errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
#if 0
CreateEvntConf* getConf() {
return &m_conf;
}
const CreateEvntConf* getConf() const {
return &m_conf;
}
#endif
// with SignalLength2
Uint32 m_masterNodeId;
Uint32 getUserRef() const {
return m_userRef;
}
@ -508,17 +475,11 @@ struct CreateEvntRef {
void setErrorNode(Uint32 val) {
m_errorNode = val;
}
Uint32 getMasterNode() const {
return m_masterNodeId;
}
void setMasterNode(Uint32 val) {
m_masterNodeId = val;
}
};
#if 0
inline bool CreateEvntRef::isTemporary() const
{ return (errorCode & CreateEvntRef::Temporary) > 0; }
inline void CreateEvntRef::setTemporary()
{ errorCode |= CreateEvntRef::Temporary; }
inline CreateEvntRef::ErrorCode CreateEvntRef::setTemporary(ErrorCode ec)
{ return (CreateEvntRef::ErrorCode)
(errorCode = ((Uint32) ec | (Uint32)CreateEvntRef::Temporary)); }
inline CreateEvntRef::ErrorCode CreateEvntRef::makeTemporary(ErrorCode ec)
{ return (CreateEvntRef::ErrorCode)
( (Uint32) ec | (Uint32)CreateEvntRef::Temporary ); }
#endif
#endif

View file

@ -146,6 +146,12 @@ public:
void setMonitorAllAttributes(bool val) {
BitmaskImpl::setField(1, &m_triggerInfo, 25, 1, val);
}
bool getReportAllMonitoredAttributes() const {
return BitmaskImpl::getField(1, &m_triggerInfo, 26, 1);
}
void setReportAllMonitoredAttributes(bool val) {
BitmaskImpl::setField(1, &m_triggerInfo, 26, 1, val);
}
Uint32 getOnline() const {
return m_online;
}

View file

@ -0,0 +1,67 @@
/* 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 */
#ifndef DIH_FRAG_COUNT_HPP
#define DIH_FRAG_COUNT_HPP
#include "SignalData.hpp"
/**
* DihFragCountReq
*/
class DihFragCountReq {
public:
STATIC_CONST( SignalLength = 3 );
STATIC_CONST( RetryInterval = 5 );
Uint32 m_connectionData;
Uint32 m_tableRef;
Uint32 m_senderData;
};
/**
* DihFragCountConf
*/
class DihFragCountConf {
public:
STATIC_CONST( SignalLength = 5 );
Uint32 m_connectionData;
Uint32 m_tableRef;
Uint32 m_senderData;
Uint32 m_fragmentCount;
Uint32 m_noOfBackups;
};
/**
* DihFragCountRef
*/
class DihFragCountRef {
public:
enum ErrorCode {
ErroneousState = 0,
ErroneousTableState = 1
};
STATIC_CONST( SignalLength = 5 );
Uint32 m_connectionData;
Uint32 m_tableRef;
Uint32 m_senderData;
Uint32 m_error;
Uint32 m_tableStatus; // Dbdih::TabRecord::tabStatus
};
#endif

View file

@ -39,7 +39,9 @@ struct SubCreateReq {
RemoveFlags = 0xff,
GetFlags = 0xff << 16,
AddTableFlag = 0x1 << 16,
RestartFlag = 0x2 << 16
RestartFlag = 0x2 << 16,
ReportAll = 0x4 << 16,
ReportSubscribe= 0x8 << 16
};
Uint32 senderRef;
@ -115,7 +117,8 @@ struct SubStartRef {
enum ErrorCode {
Undefined = 1,
NF_FakeErrorREF = 11,
Busy = 701
Busy = 701,
NotMaster = 702
};
STATIC_CONST( SignalLength = 7 );
@ -130,7 +133,10 @@ struct SubStartRef {
// do not change the order here!
Uint32 errorCode;
// with SignalLength2
Uint32 subscriberRef;
union {
Uint32 subscriberRef;
Uint32 m_masterNodeId;
};
};
struct SubStartConf {
@ -181,10 +187,12 @@ struct SubStopRef {
enum ErrorCode {
Undefined = 1,
NF_FakeErrorREF = 11,
Busy = 701
Busy = 701,
NotMaster = 702
};
STATIC_CONST( SignalLength = 8 );
STATIC_CONST( SignalLength2 = SignalLength+1 );
Uint32 senderRef;
Uint32 senderData;
@ -194,6 +202,8 @@ struct SubStopRef {
Uint32 subscriberData;
Uint32 subscriberRef;
Uint32 errorCode;
// with SignalLength2
Uint32 m_masterNodeId;
};
struct SubStopConf {
@ -304,7 +314,7 @@ struct SubTableData {
Uint32 tableId;
Uint8 operation;
Uint8 req_nodeid;
Uint8 not_used2;
Uint8 ndbd_nodeid;
Uint8 not_used3;
Uint32 logType;
};

View file

@ -1036,6 +1036,9 @@ public:
TE_GCP_COMPLETE=1<<7, ///< GCP is complete
TE_CLUSTER_FAILURE=1<<8, ///< Cluster is unavailable
TE_STOP =1<<9, ///< Stop of event operation
TE_NODE_FAILURE=1<<10, ///< Node failed
TE_SUBSCRIBE =1<<11, ///< Node subscribes
TE_UNSUBSCRIBE =1<<12, ///< Node unsubscribes
TE_ALL=0xFFFF ///< Any/all event on table (not relevant when
///< events are received)
};
@ -1052,7 +1055,10 @@ public:
_TE_GCP_COMPLETE=7,
_TE_CLUSTER_FAILURE=8,
_TE_STOP=9,
_TE_NUL=10 // internal (INS o DEL within same GCI)
_TE_NODE_FAILURE=10,
_TE_SUBSCRIBE=11,
_TE_UNSUBSCRIBE=12,
_TE_NUL=13 // internal (INS o DEL within same GCI)
};
#endif
/**
@ -1080,6 +1086,15 @@ public:
#endif
};
/**
* Specifies reporting options for table events
*/
enum EventReport {
ER_UPDATED = 0,
ER_ALL = 1,
ER_SUBSCRIBE = 2
};
/**
* Constructor
* @param name Name of event
@ -1135,6 +1150,14 @@ public:
* Get durability of the event
*/
EventDurability getDurability() const;
/**
* Set report option of the event
*/
void setReport(EventReport);
/**
* Get report option of the event
*/
EventReport getReport() const;
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
void addColumn(const Column &c);
#endif

View file

@ -173,7 +173,12 @@ struct NdbError {
/**
* Schema object already exists
*/
SchemaObjectExists = ndberror_cl_schema_object_already_exists
SchemaObjectExists = ndberror_cl_schema_object_already_exists,
/**
* Request sent to non master
*/
InternalTemporary = ndberror_cl_internal_temporary
};
/**

View file

@ -210,6 +210,7 @@ public:
int hasError() const;
int getReqNodeId() const;
int getNdbdNodeId() const;
#endif
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL

View file

@ -17,6 +17,7 @@
#ifndef CLUSTER_CONNECTION_HPP
#define CLUSTER_CONNECTION_HPP
#include <ndb_types.h>
class Ndb_cluster_connection_node_iter
{

View file

@ -50,7 +50,8 @@ typedef enum
ndberror_cl_unknown_error_code = 14,
ndberror_cl_node_shutdown = 15,
ndberror_cl_configuration = 16,
ndberror_cl_schema_object_already_exists = 17
ndberror_cl_schema_object_already_exists = 17,
ndberror_cl_internal_temporary = 18
} ndberror_classification_enum;

View file

@ -25,6 +25,7 @@
#include <signaldata/NodeFailRep.hpp>
#include <signaldata/ReadNodesConf.hpp>
#include <signaldata/DihFragCount.hpp>
#include <signaldata/ScanFrag.hpp>
#include <signaldata/GetTabInfo.hpp>
@ -1302,6 +1303,7 @@ Backup::sendCreateTrig(Signal* signal,
for (int i=0; i < 3; i++) {
req->setTriggerEvent(triggerEventValues[i]);
req->setReportAllMonitoredAttributes(false);
BaseString::snprintf(triggerName, sizeof(triggerName), triggerNameFormat[i],
ptr.p->backupId, tabPtr.p->tableId);
w.reset();
@ -2955,10 +2957,12 @@ next:
}
ndbrequire(ptr.p->tables.first(tabPtr));
signal->theData[0] = RNIL;
signal->theData[1] = tabPtr.p->tableId;
signal->theData[2] = ptr.i;
sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal, 3, JBB);
DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
req->m_connectionData = RNIL;
req->m_tableRef = tabPtr.p->tableId;
req->m_senderData = ptr.i;
sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
DihFragCountReq::SignalLength, JBB);
return;
}//if
@ -3131,11 +3135,11 @@ void
Backup::execDI_FCOUNTCONF(Signal* signal)
{
jamEntry();
const Uint32 userPtr = signal->theData[0];
const Uint32 fragCount = signal->theData[1];
const Uint32 tableId = signal->theData[2];
const Uint32 senderData = signal->theData[3];
DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
const Uint32 userPtr = conf->m_connectionData;
const Uint32 fragCount = conf->m_fragmentCount;
const Uint32 tableId = conf->m_tableRef;
const Uint32 senderData = conf->m_senderData;
ndbrequire(userPtr == RNIL && signal->length() == 5);
@ -3162,10 +3166,12 @@ Backup::execDI_FCOUNTCONF(Signal* signal)
*/
if(ptr.p->tables.next(tabPtr)) {
jam();
signal->theData[0] = RNIL;
signal->theData[1] = tabPtr.p->tableId;
signal->theData[2] = ptr.i;
sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal, 3, JBB);
DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
req->m_connectionData = RNIL;
req->m_tableRef = tabPtr.p->tableId;
req->m_senderData = ptr.i;
sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
DihFragCountReq::SignalLength, JBB);
return;
}//if

View file

@ -456,6 +456,11 @@ Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
Uint32 count = 2 + data[0] * data[1];
w.add(DictTabInfo::FragmentDataLen, 2*count);
w.add(DictTabInfo::FragmentData, data, 2*count);
ndbrequire(count > 0);
}
else
{
ndbrequire(false);
}
}
@ -2006,9 +2011,9 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
c_opCreateTable.setSize(8);
c_opDropTable.setSize(8);
c_opCreateIndex.setSize(8);
c_opCreateEvent.setSize(8);
c_opSubEvent.setSize(8);
c_opDropEvent.setSize(8);
c_opCreateEvent.setSize(2);
c_opSubEvent.setSize(2);
c_opDropEvent.setSize(2);
c_opSignalUtil.setSize(8);
c_opDropIndex.setSize(8);
c_opAlterIndex.setSize(8);
@ -7078,6 +7083,20 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal)
sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
return;
}//if
if (DictTabInfo::isTable(objEntry->m_tableType) ||
DictTabInfo::isIndex(objEntry->m_tableType))
{
jam();
TableRecordPtr tabPtr;
c_tableRecordPool.getPtr(tabPtr, obj_id);
if (tabPtr.p->tabState != TableRecord::DEFINED)
{
jam();
sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
return;
}
}
c_retrieveRecord.busyState = true;
c_retrieveRecord.blockRef = req->senderRef;
@ -8655,6 +8674,23 @@ Dbdict::execCREATE_EVNT_REQ(Signal* signal)
const CreateEvntReq::RequestType requestType = req->getRequestType();
const Uint32 requestFlag = req->getRequestFlag();
if (refToBlock(signal->senderBlockRef()) != DBDICT &&
getOwnNodeId() != c_masterNodeId)
{
jam();
releaseSections(signal);
CreateEvntRef * ref = (CreateEvntRef *)signal->getDataPtrSend();
ref->setUserRef(reference());
ref->setErrorCode(CreateEvntRef::NotMaster);
ref->setErrorLine(__LINE__);
ref->setErrorNode(reference());
ref->setMasterNode(c_masterNodeId);
sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
CreateEvntRef::SignalLength2, JBB);
return;
}
OpCreateEventPtr evntRecPtr;
// Seize a Create Event record
if (!c_opCreateEvent.seize(evntRecPtr)) {
@ -8946,7 +8982,8 @@ Dbdict::createEventUTIL_PREPARE(Signal* signal,
break;
case CreateEvntReq::RT_USER_CREATE:
{
evntRecPtr.p->m_eventRec.EVENT_TYPE = evntRecPtr.p->m_request.getEventType();
evntRecPtr.p->m_eventRec.EVENT_TYPE =
evntRecPtr.p->m_request.getEventType() | evntRecPtr.p->m_request.getReportFlags();
evntRecPtr.p->m_eventRec.TABLEID = evntRecPtr.p->m_request.getTableId();
evntRecPtr.p->m_eventRec.TABLEVERSION=evntRecPtr.p->m_request.getTableVersion();
AttributeMask m = evntRecPtr.p->m_request.getAttrListBitmask();
@ -9161,6 +9198,7 @@ void Dbdict::createEventUTIL_EXECUTE(Signal *signal,
parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
evntRec->m_request.setEventType(evntRecPtr.p->m_eventRec.EVENT_TYPE);
evntRec->m_request.setReportFlags(evntRecPtr.p->m_eventRec.EVENT_TYPE);
evntRec->m_request.setTableId(evntRecPtr.p->m_eventRec.TABLEID);
evntRec->m_request.setTableVersion(evntRecPtr.p->m_eventRec.TABLEVERSION);
evntRec->m_request.setAttrListBitmask(*(AttributeMask*)
@ -9392,6 +9430,7 @@ void Dbdict::execCREATE_EVNT_CONF(Signal* signal)
void
Dbdict::createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){
DBUG_ENTER("Dbdict::createEvent_RT_DICT_AFTER_GET");
jam();
evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
@ -9412,6 +9451,10 @@ Dbdict::createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPt
sumaReq->subscriptionId = evntRecPtr.p->m_request.getEventId();
sumaReq->subscriptionKey = evntRecPtr.p->m_request.getEventKey();
sumaReq->subscriptionType = SubCreateReq::TableEvent;
if (evntRecPtr.p->m_request.getReportAll())
sumaReq->subscriptionType|= SubCreateReq::ReportAll;
if (evntRecPtr.p->m_request.getReportSubscribe())
sumaReq->subscriptionType|= SubCreateReq::ReportSubscribe;
sumaReq->tableId = evntRecPtr.p->m_request.getTableId();
#ifdef EVENT_PH2_DEBUG
@ -9420,6 +9463,7 @@ Dbdict::createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPt
sendSignal(SUMA_REF, GSN_SUB_CREATE_REQ, signal,
SubCreateReq::SignalLength, JBB);
DBUG_VOID_RETURN;
}
void Dbdict::execSUB_CREATE_REF(Signal* signal)
@ -9582,6 +9626,20 @@ void Dbdict::execSUB_START_REQ(Signal* signal)
Uint32 origSenderRef = signal->senderBlockRef();
if (refToBlock(origSenderRef) != DBDICT &&
getOwnNodeId() != c_masterNodeId)
{
/*
* Coordinator but not master
*/
SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
ref->senderRef = reference();
ref->errorCode = SubStartRef::NotMaster;
ref->m_masterNodeId = c_masterNodeId;
sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
SubStartRef::SignalLength2, JBB);
return;
}
OpSubEventPtr subbPtr;
if (!c_opSubEvent.seize(subbPtr)) {
SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
@ -9761,6 +9819,9 @@ void Dbdict::completeSubStartReq(Signal* signal,
#ifdef EVENT_DEBUG
ndbout_c("SUB_START_REF");
#endif
SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
ref->senderRef = reference();
ref->errorCode = subbPtr.p->m_errorCode;
sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
signal, SubStartRef::SignalLength, JBB);
if (subbPtr.p->m_reqTracker.hasConf()) {
@ -9789,6 +9850,20 @@ void Dbdict::execSUB_STOP_REQ(Signal* signal)
Uint32 origSenderRef = signal->senderBlockRef();
if (refToBlock(origSenderRef) != DBDICT &&
getOwnNodeId() != c_masterNodeId)
{
/*
* Coordinator but not master
*/
SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
ref->senderRef = reference();
ref->errorCode = SubStopRef::NotMaster;
ref->m_masterNodeId = c_masterNodeId;
sendSignal(origSenderRef, GSN_SUB_STOP_REF, signal,
SubStopRef::SignalLength2, JBB);
return;
}
OpSubEventPtr subbPtr;
if (!c_opSubEvent.seize(subbPtr)) {
SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
@ -9982,6 +10057,23 @@ Dbdict::execDROP_EVNT_REQ(Signal* signal)
const Uint32 senderRef = signal->senderBlockRef();
OpDropEventPtr evntRecPtr;
if (refToBlock(senderRef) != DBDICT &&
getOwnNodeId() != c_masterNodeId)
{
jam();
releaseSections(signal);
DropEvntRef * ref = (DropEvntRef *)signal->getDataPtrSend();
ref->setUserRef(reference());
ref->setErrorCode(DropEvntRef::NotMaster);
ref->setErrorLine(__LINE__);
ref->setErrorNode(reference());
ref->setMasterNode(c_masterNodeId);
sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
DropEvntRef::SignalLength2, JBB);
return;
}
// Seize a Create Event record
if (!c_opDropEvent.seize(evntRecPtr)) {
// Failed to allocate event record
@ -10825,6 +10917,7 @@ Dbdict::alterIndex_toCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr)
if (indexPtr.p->isHashIndex()) {
req->setTriggerType(TriggerType::SECONDARY_INDEX);
req->setMonitorReplicas(false);
req->setReportAllMonitoredAttributes(true);
// insert
if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
req->setTriggerId(indexPtr.p->insertTriggerId);
@ -10867,6 +10960,7 @@ Dbdict::alterIndex_toCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr)
req->setTriggerType(TriggerType::ORDERED_INDEX);
req->setTriggerActionTime(TriggerActionTime::TA_CUSTOM);
req->setMonitorReplicas(true);
req->setReportAllMonitoredAttributes(true);
// one trigger for 5 events (insert, update, delete, commit, abort)
if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
req->setTriggerId(indexPtr.p->customTriggerId);
@ -11383,6 +11477,7 @@ Dbdict::buildIndex_toCreateConstr(Signal* signal, OpBuildIndexPtr opPtr)
req->setTriggerEvent(TriggerEvent::TE_UPDATE);
req->setMonitorReplicas(false);
req->setMonitorAllAttributes(false);
req->setReportAllMonitoredAttributes(true);
req->setOnline(true); // alter online after create
req->setReceiverRef(0); // no receiver, REF-ed by TUP
req->getAttributeMask().clear();
@ -11942,6 +12037,7 @@ Dbdict::createTrigger_slaveCreate(Signal* signal, OpCreateTriggerPtr opPtr)
triggerPtr.p->triggerEvent = req->getTriggerEvent();
triggerPtr.p->monitorReplicas = req->getMonitorReplicas();
triggerPtr.p->monitorAllAttributes = req->getMonitorAllAttributes();
triggerPtr.p->reportAllMonitoredAttributes = req->getReportAllMonitoredAttributes();
triggerPtr.p->attributeMask = req->getAttributeMask();
triggerPtr.p->triggerState = TriggerRecord::TS_OFFLINE;
// add to hash table
@ -12774,6 +12870,7 @@ Dbdict::alterTrigger_toCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
req->setTriggerEvent(triggerPtr.p->triggerEvent);
req->setMonitorReplicas(triggerPtr.p->monitorReplicas);
req->setMonitorAllAttributes(triggerPtr.p->monitorAllAttributes);
req->setReportAllMonitoredAttributes(triggerPtr.p->reportAllMonitoredAttributes);
req->setOnline(true);
req->setReceiverRef(opPtr.p->m_request.getReceiverRef());
BlockReference blockRef = 0;

View file

@ -414,7 +414,10 @@ public:
/** Monitor all, the trigger monitors changes of all attributes in table */
bool monitorAllAttributes;
/** Monitor all, the trigger monitors changes of all attributes in table */
bool reportAllMonitoredAttributes;
/**
* Attribute mask, defines what attributes are to be monitored.
* Can be seen as a compact representation of SQL column name list.
@ -1580,16 +1583,15 @@ private:
RequestTracker m_reqTracker;
// state info
CreateEvntReq::RequestType m_requestType;
Uint32 m_requestFlag;
// error info
Uint32 m_errorCode;
Uint32 m_errorLine;
Uint32 m_errorNode;
Uint32 m_errorNode; /* also used to store master node id
in case of NotMaster */
// ctor
OpCreateEvent() {
memset(&m_request, 0, sizeof(m_request));
m_requestType = CreateEvntReq::RT_UNDEFINED;
m_requestFlag = 0;
m_errorCode = CreateEvntRef::NoError;
m_errorLine = 0;
m_errorNode = 0;
@ -1600,7 +1602,6 @@ private:
m_errorLine = 0;
m_errorNode = 0;
m_requestType = req->getRequestType();
m_requestFlag = req->getRequestFlag();
}
bool hasError() {
return m_errorCode != CreateEvntRef::NoError;

View file

@ -67,12 +67,6 @@
// Error Codes for Add Table
// --------------------------------------
#define ZREPLERROR1 306
#define ZNOTIMPLEMENTED 307
#define ZTABLEINSTALLED 310
// --------------------------------------
// Error Codes for Scan Table
// --------------------------------------
#define ZERRONOUSSTATE 308
// --------------------------------------
// Crash Codes

Some files were not shown because too many files have changed in this diff Show more