summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2019-12-03 14:45:06 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2019-12-03 14:45:06 +0100
commitf8b5e147da18d0baa7345aed0deec0fd40666d19 (patch)
treec0b0cbb9bc0f5afd6ca123604a67323bdc521099
parent543f22a2d0633e645fb49a360c55528d8cb008fb (diff)
parent117c8146de7ccfaf2331225d6fb264de71aa6779 (diff)
downloadmariadb-git-f8b5e147da18d0baa7345aed0deec0fd40666d19.tar.gz
Merge branch '10.1' into 10.2
-rw-r--r--client/mysql.cc6
-rw-r--r--dbug/dbug.c146
-rw-r--r--man/mysql-test-run.pl.16
-rwxr-xr-xmysql-test/mysql-test-run.pl48
-rw-r--r--mysql-test/r/mysqld--help.result2
-rw-r--r--mysql-test/r/order_by.result30
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_ctas.result14
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result21
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_ctas.cnf5
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_ctas.test75
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.cnf6
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test65
-rw-r--r--mysql-test/t/order_by.test16
-rw-r--r--scripts/mysql_install_db.sh2
-rw-r--r--sql/filesort.cc1
-rw-r--r--sql/log_event.h3
-rw-r--r--sql/mysqld.cc4
-rw-r--r--sql/slave.cc33
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/wsrep_hton.cc21
-rw-r--r--sql/wsrep_mysqld.cc34
-rw-r--r--storage/connect/inihandl.cpp2
-rw-r--r--storage/innobase/os/os0thread.cc10
23 files changed, 435 insertions, 117 deletions
diff --git a/client/mysql.cc b/client/mysql.cc
index 2247e93ca93..d672473798e 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -3213,7 +3213,7 @@ static int
com_go(String *buffer,char *line __attribute__((unused)))
{
char buff[200]; /* about 110 chars used so far */
- char time_buff[52+3+1]; /* time max + space&parens + NUL */
+ char time_buff[52+3+1]; /* time max + space & parens + NUL */
MYSQL_RES *result;
ulong timer, warnings= 0;
uint error= 0;
@@ -3232,7 +3232,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
if (buffer->is_empty())
{
- if (status.batch) // Ignore empty quries
+ if (status.batch) // Ignore empty queries.
return 0;
return put_info("No query specified\n",INFO_ERROR);
@@ -3297,7 +3297,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
else
time_buff[0]= '\0';
- /* Every branch must truncate buff . */
+ /* Every branch must truncate buff. */
if (result)
{
if (!mysql_num_rows(result) && ! quick && !column_types_flag)
diff --git a/dbug/dbug.c b/dbug/dbug.c
index 9845fee0948..cde6363c86a 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -320,8 +320,36 @@ static void DbugVfprintf(FILE *stream, const char* format, va_list args);
*/
#include <my_pthread.h>
+/*
+** Protects writing to all file descriptors, init_settings.keywords
+** pointer and it's pointee - a linked list with keywords.
+*/
static pthread_mutex_t THR_LOCK_dbug;
+static void LockMutex(CODE_STATE *cs)
+{
+ if (!cs->locked)
+ pthread_mutex_lock(&THR_LOCK_dbug);
+ cs->locked++;
+}
+static void UnlockMutex(CODE_STATE *cs)
+{
+ --cs->locked;
+ assert(cs->locked >= 0);
+ if (cs->locked == 0)
+ pthread_mutex_unlock(&THR_LOCK_dbug);
+}
+static void LockIfInitSettings(CODE_STATE *cs)
+{
+ if (cs->stack == &init_settings)
+ LockMutex(cs);
+}
+static void UnlockIfInitSettings(CODE_STATE *cs)
+{
+ if (cs->stack == &init_settings)
+ UnlockMutex(cs);
+}
+
static CODE_STATE *code_state(void)
{
CODE_STATE *cs, **cs_ptr;
@@ -449,16 +477,9 @@ static int DbugParse(CODE_STATE *cs, const char *control)
const char *end;
int rel, f_used=0;
struct settings *stack;
- int org_cs_locked;
stack= cs->stack;
- if (!(org_cs_locked= cs->locked))
- {
- pthread_mutex_lock(&THR_LOCK_dbug);
- cs->locked= 1;
- }
-
if (control[0] == '-' && control[1] == '#')
control+=2;
@@ -472,7 +493,9 @@ static int DbugParse(CODE_STATE *cs, const char *control)
stack->sub_level= 0;
stack->out_file= sstderr;
stack->functions= NULL;
+ LockIfInitSettings(cs);
stack->keywords= NULL;
+ UnlockIfInitSettings(cs);
stack->processes= NULL;
}
else if (!stack->out_file)
@@ -488,7 +511,9 @@ static int DbugParse(CODE_STATE *cs, const char *control)
{
/* never share with the global parent - it can change under your feet */
stack->functions= ListCopy(init_settings.functions);
+ LockIfInitSettings(cs);
stack->keywords= ListCopy(init_settings.keywords);
+ UnlockIfInitSettings(cs);
stack->processes= ListCopy(init_settings.processes);
}
else
@@ -512,21 +537,31 @@ static int DbugParse(CODE_STATE *cs, const char *control)
case 'd':
if (sign < 0 && control == end)
{
+ LockIfInitSettings(cs);
if (!is_shared(stack, keywords))
FreeList(stack->keywords);
stack->keywords=NULL;
+ UnlockIfInitSettings(cs);
stack->flags &= ~DEBUG_ON;
break;
}
+ LockIfInitSettings(cs);
if (rel && is_shared(stack, keywords))
stack->keywords= ListCopy(stack->keywords);
+ UnlockIfInitSettings(cs);
if (sign < 0)
{
if (DEBUGGING)
+ {
+ LockIfInitSettings(cs);
stack->keywords= ListDel(stack->keywords, control, end);
+ UnlockIfInitSettings(cs);
+ }
break;
}
+ LockIfInitSettings(cs);
stack->keywords= ListAdd(stack->keywords, control, end);
+ UnlockIfInitSettings(cs);
stack->flags |= DEBUG_ON;
break;
case 'D':
@@ -661,11 +696,6 @@ static int DbugParse(CODE_STATE *cs, const char *control)
control=end+1;
end= DbugStrTok(control);
}
- if (!org_cs_locked)
- {
- cs->locked= 0;
- pthread_mutex_unlock(&THR_LOCK_dbug);
- }
return !rel || f_used;
}
@@ -998,7 +1028,9 @@ int _db_explain_ (CODE_STATE *cs, char *buf, size_t len)
get_code_state_if_not_set_or_return *buf=0;
+ LockIfInitSettings(cs);
op_list_to_buf('d', cs->stack->keywords, DEBUGGING);
+ UnlockIfInitSettings(cs);
op_int_to_buf ('D', cs->stack->delay, 0);
op_list_to_buf('f', cs->stack->functions, cs->stack->functions);
op_bool_to_buf('F', cs->stack->flags & FILE_ON);
@@ -1093,7 +1125,6 @@ int _db_explain_init_(char *buf, size_t len)
void _db_enter_(const char *_func_, const char *_file_,
uint _line_, struct _db_stack_frame_ *_stack_frame_)
{
- int save_errno, org_cs_locked;
CODE_STATE *cs;
if (!((cs=code_state())))
{
@@ -1101,7 +1132,6 @@ void _db_enter_(const char *_func_, const char *_file_,
_stack_frame_->prev= 0;
return;
}
- save_errno= errno;
_stack_frame_->line= -1;
_stack_frame_->func= cs->func;
@@ -1122,20 +1152,14 @@ void _db_enter_(const char *_func_, const char *_file_,
cs->stack->flags &= ~SANITY_CHECK_ON;
if (TRACING)
{
- if (!(org_cs_locked= cs->locked))
- {
- pthread_mutex_lock(&THR_LOCK_dbug);
- cs->locked= 1;
- }
+ int save_errno= errno;
+ LockMutex(cs);
DoPrefix(cs, _line_);
Indent(cs, cs->level);
(void) fprintf(cs->stack->out_file->file, ">%s\n", cs->func);
- DbugFlush(cs); /* This does a unlock */
- if (!org_cs_locked)
- {
- cs->locked= 0;
- pthread_mutex_unlock(&THR_LOCK_dbug);
- }
+ UnlockMutex(cs);
+ DbugFlush(cs);
+ errno=save_errno;
}
break;
case DISABLE_TRACE:
@@ -1144,7 +1168,6 @@ void _db_enter_(const char *_func_, const char *_file_,
case DONT_TRACE:
break;
}
- errno=save_errno;
}
/*
@@ -1169,7 +1192,6 @@ void _db_enter_(const char *_func_, const char *_file_,
void _db_return_(struct _db_stack_frame_ *_stack_frame_)
{
- int save_errno=errno;
uint _slevel_= _stack_frame_->level & ~TRACE_ON;
CODE_STATE *cs;
get_code_state_or_return;
@@ -1186,25 +1208,18 @@ void _db_return_(struct _db_stack_frame_ *_stack_frame_)
if (DoTrace(cs) & DO_TRACE)
{
- int org_cs_locked;
if ((cs->stack->flags & SANITY_CHECK_ON) && sf_sanity())
cs->stack->flags &= ~SANITY_CHECK_ON;
if (TRACING)
{
- if (!(org_cs_locked= cs->locked))
- {
- pthread_mutex_lock(&THR_LOCK_dbug);
- cs->locked= 1;
- }
+ int save_errno=errno;
+ LockMutex(cs);
DoPrefix(cs, _stack_frame_->line);
Indent(cs, cs->level);
(void) fprintf(cs->stack->out_file->file, "<%s\n", cs->func);
+ UnlockMutex(cs);
DbugFlush(cs);
- if (!org_cs_locked)
- {
- cs->locked= 0;
- pthread_mutex_unlock(&THR_LOCK_dbug);
- }
+ errno=save_errno;
}
}
/*
@@ -1216,7 +1231,6 @@ void _db_return_(struct _db_stack_frame_ *_stack_frame_)
cs->file= _stack_frame_->file;
if (cs->framep != NULL)
cs->framep= cs->framep->prev;
- errno=save_errno;
}
@@ -1281,18 +1295,14 @@ void _db_doprnt_(const char *format,...)
{
va_list args;
CODE_STATE *cs;
- int save_errno, org_cs_locked;
+ int save_errno;
get_code_state_or_return;
va_start(args,format);
- if (!(org_cs_locked= cs->locked))
- {
- pthread_mutex_lock(&THR_LOCK_dbug);
- cs->locked= 1;
- }
save_errno=errno;
+ LockMutex(cs);
DoPrefix(cs, cs->u_line);
if (TRACING)
Indent(cs, cs->level + 1);
@@ -1300,12 +1310,8 @@ void _db_doprnt_(const char *format,...)
(void) fprintf(cs->stack->out_file->file, "%s: ", cs->func);
(void) fprintf(cs->stack->out_file->file, "%s: ", cs->u_keyword);
DbugVfprintf(cs->stack->out_file->file, format, args);
+ UnlockMutex(cs);
DbugFlush(cs);
- if (!org_cs_locked)
- {
- cs->locked= 0;
- pthread_mutex_unlock(&THR_LOCK_dbug);
- }
errno=save_errno;
va_end(args);
@@ -1345,17 +1351,13 @@ static void DbugVfprintf(FILE *stream, const char* format, va_list args)
void _db_dump_(uint _line_, const char *keyword,
const unsigned char *memory, size_t length)
{
- int pos, org_cs_locked;
+ int pos;
CODE_STATE *cs;
get_code_state_or_return;
- if (!(org_cs_locked= cs->locked))
- {
- pthread_mutex_lock(&THR_LOCK_dbug);
- cs->locked= 1;
- }
if (_db_keyword_(cs, keyword, 0))
{
+ LockMutex(cs);
DoPrefix(cs, _line_);
if (TRACING)
{
@@ -1383,13 +1385,9 @@ void _db_dump_(uint _line_, const char *keyword,
fputc(' ',cs->stack->out_file->file);
}
(void) fputc('\n',cs->stack->out_file->file);
+ UnlockMutex(cs);
DbugFlush(cs);
}
- if (!org_cs_locked)
- {
- cs->locked= 0;
- pthread_mutex_unlock(&THR_LOCK_dbug);
- }
}
@@ -1617,8 +1615,10 @@ static void PushState(CODE_STATE *cs)
static void FreeState(CODE_STATE *cs, int free_state)
{
struct settings *state= cs->stack;
+ LockIfInitSettings(cs);
if (!is_shared(state, keywords))
FreeList(state->keywords);
+ UnlockIfInitSettings(cs);
if (!is_shared(state, functions))
FreeList(state->functions);
if (!is_shared(state, processes))
@@ -1697,8 +1697,6 @@ void _db_end_()
static int DoTrace(CODE_STATE *cs)
{
int res= DONT_TRACE;
- if (!cs->locked)
- pthread_mutex_lock(&THR_LOCK_dbug);
if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) &&
InList(cs->stack->processes, cs->process, 0) & (MATCHED|INCLUDE))
{
@@ -1723,8 +1721,6 @@ static int DoTrace(CODE_STATE *cs)
break;
}
}
- if (!cs->locked)
- pthread_mutex_unlock(&THR_LOCK_dbug);
return res;
}
@@ -1764,11 +1760,9 @@ BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict)
if (!(DEBUGGING && (DoTrace(cs) & DO_TRACE)))
return 0;
- if (!cs->locked)
- pthread_mutex_lock(&THR_LOCK_dbug);
+ LockIfInitSettings(cs);
res= (InList(cs->stack->keywords, keyword, strict) & match);
- if (!cs->locked)
- pthread_mutex_unlock(&THR_LOCK_dbug);
+ UnlockIfInitSettings(cs);
return res != 0;
}
@@ -1995,16 +1989,16 @@ static void DBUGCloseFile(CODE_STATE *cs, sFILE *new_value)
sFILE *fp;
if (!cs || !cs->stack || !cs->stack->out_file)
return;
- if (!cs->locked)
- pthread_mutex_lock(&THR_LOCK_dbug);
fp= cs->stack->out_file;
if (--fp->used == 0)
{
if (fclose(fp->file) == EOF)
{
+ LockMutex(cs);
(void) fprintf(stderr, ERR_CLOSE, cs->process);
perror("");
+ UnlockMutex(cs);
}
else
{
@@ -2012,8 +2006,6 @@ static void DBUGCloseFile(CODE_STATE *cs, sFILE *new_value)
}
}
cs->stack->out_file= new_value;
- if (!cs->locked)
- pthread_mutex_unlock(&THR_LOCK_dbug);
}
@@ -2196,9 +2188,7 @@ void _db_flush_()
get_code_state_or_return;
if (DEBUGGING)
{
- pthread_mutex_lock(&THR_LOCK_dbug);
(void) fflush(cs->stack->out_file->file);
- pthread_mutex_unlock(&THR_LOCK_dbug);
}
}
@@ -2226,16 +2216,14 @@ void _db_lock_file_()
{
CODE_STATE *cs;
get_code_state_or_return;
- pthread_mutex_lock(&THR_LOCK_dbug);
- cs->locked=1;
+ LockMutex(cs);
}
void _db_unlock_file_()
{
CODE_STATE *cs;
get_code_state_or_return;
- cs->locked=0;
- pthread_mutex_unlock(&THR_LOCK_dbug);
+ UnlockMutex(cs);
}
const char* _db_get_func_(void)
diff --git a/man/mysql-test-run.pl.1 b/man/mysql-test-run.pl.1
index a2153ac57fe..e5489e5219e 100644
--- a/man/mysql-test-run.pl.1
+++ b/man/mysql-test-run.pl.1
@@ -1937,8 +1937,10 @@ Run stress test, providing options to mysql\-stress\-test\&.pl\&. Options are se
.\" suite option: mysql-test-run.pl
\fB\-\-suite[s]=\fR\fB\fIsuite_name...\fR\fR
.sp
-Comma separated list of suite names to run. The default is: "main-,archive-,binlog-,csv-,federated-,funcs_1-,funcs_2-,handler-,heap-,innodb-,innodb_fts-,
-innodb_zip-,maria-,multi_source-,optimizer_unfixed_bugs-,parts-,percona-,perfschema-,
+Comma separated list of suite names to run. The default is:
+"main-,archive-,binlog-,csv-,federated-,funcs_1-,funcs_2-,
+handler-,heap-,innodb-,innodb_fts-,innodb_zip-,maria-,
+multi_source-,optimizer_unfixed_bugs-,parts-,perfschema-,
plugins-,roles-,rpl-,sys_vars-,unit-,vcol-"\&.
.RE
.sp
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index f3135e07eb4..aae2e20e23c 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -321,7 +321,8 @@ my $opt_valgrind_mysqld= 0;
my $opt_valgrind_mysqltest= 0;
my @valgrind_args;
my $opt_strace= 0;
-my $opt_strace_client;
+my $opt_stracer;
+my $opt_client_strace = 0;
my @strace_args;
my $opt_valgrind_path;
my $valgrind_reports= 0;
@@ -1324,9 +1325,10 @@ sub command_line_setup {
'debugger=s' => \$opt_debugger,
'boot-dbx' => \$opt_boot_dbx,
'client-debugger=s' => \$opt_client_debugger,
- 'strace' => \$opt_strace,
- 'strace-client' => \$opt_strace_client,
- 'strace-option=s' => \@strace_args,
+ 'strace' => \$opt_strace,
+ 'strace-option=s' => \@strace_args,
+ 'client-strace' => \$opt_client_strace,
+ 'stracer=s' => \$opt_stracer,
'max-save-core=i' => \$opt_max_save_core,
'max-save-datadir=i' => \$opt_max_save_datadir,
'max-test-fail=i' => \$opt_max_test_fail,
@@ -1921,7 +1923,7 @@ sub command_line_setup {
join(" ", @valgrind_args), "\"");
}
- if (@strace_args)
+ if (@strace_args || $opt_stracer)
{
$opt_strace=1;
}
@@ -5845,14 +5847,6 @@ sub start_mysqltest ($) {
mtr_add_arg($args, "--non-blocking-api");
}
- if ( $opt_strace_client )
- {
- $exe= $opt_strace_client || "strace";
- mtr_add_arg($args, "-o");
- mtr_add_arg($args, "%s/log/mysqltest.strace", $opt_vardir);
- mtr_add_arg($args, "$exe_mysqltest");
- }
-
mtr_add_arg($args, "--timer-file=%s/log/timer", $opt_vardir);
if ( $opt_compress )
@@ -5918,6 +5912,17 @@ sub start_mysqltest ($) {
mtr_add_arg($args, "%s", $_) for @args_saved;
}
+ # ----------------------------------------------------------------------
+ # Prefix the strace options to the argument list.
+ # ----------------------------------------------------------------------
+ if ( $opt_client_strace )
+ {
+ my @args_saved = @$args;
+ mtr_init_args(\$args);
+ strace_arguments($args, \$exe, "mysqltest");
+ mtr_add_arg($args, "%s", $_) for @args_saved;
+ }
+
if ($opt_force > 1)
{
mtr_add_arg($args, "--continue-on-error");
@@ -6242,16 +6247,17 @@ sub strace_arguments {
my $args= shift;
my $exe= shift;
my $mysqld_name= shift;
+ my $output= sprintf("%s/log/%s.strace", $path_vardir_trace, $mysqld_name);
mtr_add_arg($args, "-f");
- mtr_add_arg($args, "-o%s/var/log/%s.strace", $glob_mysql_test_dir, $mysqld_name);
+ mtr_add_arg($args, "-o%s", $output);
- # Add strace options, can be overridden by user
+ # Add strace options
mtr_add_arg($args, '%s', $_) for (@strace_args);
mtr_add_arg($args, $$exe);
- $$exe= "strace";
+ $$exe= $opt_stracer || "strace";
if ($exe_libtool)
{
@@ -6527,11 +6533,11 @@ Options for valgrind
Options for strace
strace Run the "mysqld" executables using strace. Default
- options are -f -o var/log/'mysqld-name'.strace
- strace-option=ARGS Option to give strace, replaces default option(s),
- strace-client=[path] Create strace output for mysqltest client, optionally
- specifying name and path to the trace program to use.
- Example: $0 --strace-client=ktrace
+ options are -f -o 'vardir'/log/'mysqld-name'.strace.
+ client-strace Trace the "mysqltest".
+ strace-option=ARGS Option to give strace, appends to existing options.
+ stracer=<EXE> Specify name and path to the trace program to use.
+ Default is "strace". Example: $0 --stracer=ktrace.
Misc options
user=USER User for connecting to mysqld(default: $opt_user)
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index 8bdf994f908..6ac6f34f74e 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -1544,5 +1544,5 @@ userstat FALSE
verbose TRUE
wait-timeout 28800
-To see what values a running MySQL server is using, type
+To see what variables a running MySQL server is using, type
'mysqladmin variables' instead of 'mysqld --verbose --help'.
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 28b63dab22e..e739b278746 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -3206,6 +3206,36 @@ pk
3
DROP TABLE t1;
#
+# MDEV-21044: Wrong result when using a smaller size for sort buffer
+#
+create table t1(a varchar(765),b int);
+insert into t1 values ("a",1),("b",2),("c",3),("e",4);
+insert into t1 values ("d",5),("f",6),("g",7),("h",8);
+insert into t1 values ("k",11),("l",12),("i",9),("j",10);
+insert into t1 values ("m",13),("n",14),("o",15),("p",16);
+set @save_sort_buffer_size= @@sort_buffer_size;
+set sort_buffer_size=1024;
+select * from t1 order by b;
+a b
+a 1
+b 2
+c 3
+e 4
+d 5
+f 6
+g 7
+h 8
+i 9
+j 10
+k 11
+l 12
+m 13
+n 14
+o 15
+p 16
+set @@sort_buffer_size= @save_sort_buffer_size;
+drop table t1;
+#
# MDEV-13994: Bad join results with orderby_uses_equalities=on
#
CREATE TABLE books (
diff --git a/mysql-test/suite/galera/r/galera_as_slave_ctas.result b/mysql-test/suite/galera/r/galera_as_slave_ctas.result
new file mode 100644
index 00000000000..79114824008
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_as_slave_ctas.result
@@ -0,0 +1,14 @@
+START SLAVE;
+SHOW VARIABLES LIKE 'binlog_format';
+Variable_name Value
+binlog_format ROW
+CREATE TABLE source (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE target AS SELECT * FROM source;
+DROP TABLE target;
+INSERT INTO source VALUES(1);
+CREATE TABLE target AS SELECT * FROM source;
+DROP TABLE source;
+DROP TABLE target;
+STOP SLAVE;
+RESET SLAVE ALL;
+RESET MASTER;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result
new file mode 100644
index 00000000000..d9a87571655
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result
@@ -0,0 +1,21 @@
+ALTER TABLE mysql.gtid_slave_pos engine = InnoDB;
+START SLAVE;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(1);
+SELECT LENGTH(@@global.gtid_binlog_state) > 1;
+LENGTH(@@global.gtid_binlog_state) > 1
+1
+gtid_binlog_state_equal
+0
+SELECT COUNT(*) = 0 FROM t1;
+COUNT(*) = 0
+1
+gtid_binlog_state_equal
+0
+#cleanup
+DROP TABLE t1;
+reset master;
+STOP SLAVE;
+RESET SLAVE ALL;
+reset master;
+reset master;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_ctas.cnf b/mysql-test/suite/galera/t/galera_as_slave_ctas.cnf
new file mode 100644
index 00000000000..eab2a6de90d
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_ctas.cnf
@@ -0,0 +1,5 @@
+!include ../galera_2nodes_as_slave.cnf
+
+# make sure master server uses ROW format for replication
+[mysqld]
+binlog-format=row
diff --git a/mysql-test/suite/galera/t/galera_as_slave_ctas.test b/mysql-test/suite/galera/t/galera_as_slave_ctas.test
new file mode 100644
index 00000000000..1a5e023b981
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_ctas.test
@@ -0,0 +1,75 @@
+#
+# Test Galera as a slave to a MySQL master
+#
+# The galera/galera_2node_slave.cnf describes the setup of the nodes
+# also, for this test, master server must have binlog_format=ROW
+#
+
+--source include/have_innodb.inc
+
+# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--source include/galera_cluster.inc
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+
+--connection node_2
+--disable_query_log
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--enable_query_log
+START SLAVE;
+
+
+# make sure master server has binlog_format=ROW
+--connection node_1
+SHOW VARIABLES LIKE 'binlog_format';
+
+#
+# test phase one, issue CTAS with empty source table
+#
+--connection node_1
+CREATE TABLE source (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
+
+CREATE TABLE target AS SELECT * FROM source;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
+--source include/wait_condition.inc
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
+--source include/wait_condition.inc
+
+#
+# test phase two, issue CTAS with populated source table
+#
+--connection node_1
+DROP TABLE target;
+INSERT INTO source VALUES(1);
+
+CREATE TABLE target AS SELECT * FROM source;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM target;
+--source include/wait_condition.inc
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 1 FROM target;
+--source include/wait_condition.inc
+
+--connection node_1
+DROP TABLE source;
+DROP TABLE target;
+
+--connection node_3
+--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target';
+--source include/wait_condition.inc
+
+
+--connection node_2
+STOP SLAVE;
+RESET SLAVE ALL;
+
+--connection node_1
+RESET MASTER;
+
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.cnf b/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.cnf
new file mode 100644
index 00000000000..01d2eb12630
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.cnf
@@ -0,0 +1,6 @@
+!include ../galera_2nodes_as_slave.cnf
+
+[mysqld]
+log-bin=mysqld-bin
+log-slave-updates
+binlog-format=ROW
diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test
new file mode 100644
index 00000000000..faa9ddfd5c8
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test
@@ -0,0 +1,65 @@
+#
+# Test Galera as a slave to a MariaDB master using GTIDs
+#
+# suite/galera/galera_2nodes_as_slave.cnf describes the setup of the nodes
+# suite/galera/t/galera_as_slave_gtid.cnf has the GTID options
+#
+# This test will replicate writes to MyISAM table and check that slave node is able
+# to apply them.
+# mysql.gtid_slave_pos table should be defined as innodb engine, original problem
+# by writes to mysql.gtid_slave_pos, whereas the replicated transaction contained
+# no innodb writes
+#
+
+--source include/have_innodb.inc
+
+# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--source include/galera_cluster.inc
+
+--connection node_2
+# make sure gtid_slave_pos is of innodb engine, mtr does not currently provide that
+ALTER TABLE mysql.gtid_slave_pos engine = InnoDB;
+
+--disable_query_log
+--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1;
+--enable_query_log
+START SLAVE;
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(1);
+
+SELECT LENGTH(@@global.gtid_binlog_state) > 1;
+--let $gtid_binlog_state_node1 = `SELECT @@global.gtid_binlog_state;`
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
+--source include/wait_condition.inc
+
+--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
+--source include/wait_condition.inc
+
+--disable_query_log
+--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal;
+--enable_query_log
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+SELECT COUNT(*) = 0 FROM t1;
+
+--disable_query_log
+--eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal;
+--enable_query_log
+
+--echo #cleanup
+--connection node_1
+DROP TABLE t1;
+reset master;
+
+--connection node_2
+STOP SLAVE;
+RESET SLAVE ALL;
+reset master;
+
+--connection node_3
+reset master;
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index d67c67de89c..78c16a0cd4c 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -2146,6 +2146,22 @@ SELECT DISTINCT pk FROM t1;
DROP TABLE t1;
--echo #
+--echo # MDEV-21044: Wrong result when using a smaller size for sort buffer
+--echo #
+
+create table t1(a varchar(765),b int);
+insert into t1 values ("a",1),("b",2),("c",3),("e",4);
+insert into t1 values ("d",5),("f",6),("g",7),("h",8);
+insert into t1 values ("k",11),("l",12),("i",9),("j",10);
+insert into t1 values ("m",13),("n",14),("o",15),("p",16);
+set @save_sort_buffer_size= @@sort_buffer_size;
+set sort_buffer_size=1024;
+select * from t1 order by b;
+set @@sort_buffer_size= @save_sort_buffer_size;
+drop table t1;
+
+
+--echo #
--echo # MDEV-13994: Bad join results with orderby_uses_equalities=on
--echo #
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index b2e38ae6641..38f12b5bd03 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -245,7 +245,7 @@ cannot_find_file()
echo "If you compiled from source, you need to either run 'make install' to"
echo "copy the software into the correct location ready for operation."
echo "If you don't want to do a full install, you can use the --srcdir"
- echo "option to only install the mysql database and privilege tables"
+ echo "option to only install the mysql database and privilege tables."
echo
echo "If you are using a binary release, you must either be at the top"
echo "level of the extracted archive, or pass the --basedir option"
diff --git a/sql/filesort.cc b/sql/filesort.cc
index f6530124b60..1df2f93676d 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -321,6 +321,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
param.max_keys_per_buffer=((param.max_keys_per_buffer *
(param.rec_length + sizeof(char*))) /
param.rec_length - 1);
+ set_if_bigger(param.max_keys_per_buffer, 1);
maxbuffer--; // Offset from 0
if (merge_many_buff(&param,
(uchar*) sort->get_sort_keys(),
diff --git a/sql/log_event.h b/sql/log_event.h
index a15b2168dda..368d9616daf 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -5191,6 +5191,9 @@ bool event_that_should_be_ignored(const char *buf);
bool event_checksum_test(uchar *buf, ulong event_len, enum_binlog_checksum_alg alg);
enum enum_binlog_checksum_alg get_checksum_alg(const char* buf, ulong len);
extern TYPELIB binlog_checksum_typelib;
+#ifdef WITH_WSREP
+enum Log_event_type wsrep_peak_event(rpl_group_info *rgi, ulonglong* event_size);
+#endif /* WITH_WSREP */
/**
@} (end of group Replication)
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 34e5704bcfe..58106add403 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -8754,8 +8754,8 @@ static void usage(void)
"\nbecause execution stopped before plugins were initialized.");
}
- puts("\nTo see what values a running MySQL server is using, type"
- "\n'mysqladmin variables' instead of 'mysqld --verbose --help'.");
+ puts("\nTo see what variables a running MySQL server is using, type"
+ "\n'mysqladmin variables' instead of 'mysqld --verbose --help'.");
}
DBUG_VOID_RETURN;
}
diff --git a/sql/slave.cc b/sql/slave.cc
index 1bc21f8895b..17abf8d53f3 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -304,6 +304,9 @@ handle_slave_background(void *arg __attribute__((unused)))
thd->store_globals();
thd->security_ctx->skip_grants();
thd->set_command(COM_DAEMON);
+#ifdef WITH_WSREP
+ thd->variables.wsrep_on= 0;
+#endif
thd_proc_info(thd, "Loading slave GTID position from table");
if (rpl_load_gtid_slave_state(thd))
@@ -4309,7 +4312,9 @@ pthread_handler_t handle_slave_io(void *arg)
goto err;
}
-
+#ifdef WITH_WSREP
+ thd->variables.wsrep_on= 0;
+#endif
if (RUN_HOOK(binlog_relay_io, thread_start, (thd, mi)))
{
mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL,
@@ -7389,7 +7394,33 @@ err:
sql_print_error("Error reading relay log event: %s", errmsg);
DBUG_RETURN(0);
}
+#ifdef WITH_WSREP
+enum Log_event_type wsrep_peak_event(rpl_group_info *rgi, ulonglong* event_size)
+{
+ mysql_mutex_lock(&rgi->rli->data_lock);
+
+ unsigned long long event_pos= rgi->event_relay_log_pos;
+ unsigned long long future_pos= rgi->future_event_relay_log_pos;
+ /* scan the log to read next event */
+ my_b_seek(rgi->rli->cur_log, future_pos);
+ rgi->rli->event_relay_log_pos= future_pos;
+ rgi->event_relay_log_pos= future_pos;
+
+ Log_event* ev = next_event(rgi, event_size);
+ enum Log_event_type ev_type= (ev) ? ev->get_type_code() : UNKNOWN_EVENT;
+ delete ev;
+
+ /* scan the log back and re-set the positions to original values */
+ rgi->rli->event_relay_log_pos= event_pos;
+ rgi->event_relay_log_pos= event_pos;
+ my_b_seek(rgi->rli->cur_log, future_pos);
+
+ mysql_mutex_unlock(&rgi->rli->data_lock);
+
+ return ev_type;
+}
+#endif /* WITH_WSREP */
/*
Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
because of size is simpler because when we do it we already have all relevant
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b8f23cd135b..c9cb533aa33 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -19865,7 +19865,7 @@ join_read_last(JOIN_TAB *tab)
{
TABLE *table=tab->table;
int error= 0;
- DBUG_ENTER("join_read_first");
+ DBUG_ENTER("join_read_last");
DBUG_ASSERT(table->no_keyread ||
!table->covering_keys.is_set(tab->index) ||
diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc
index c34e14b7e1f..6cf29c43447 100644
--- a/sql/wsrep_hton.cc
+++ b/sql/wsrep_hton.cc
@@ -479,12 +479,29 @@ wsrep_run_wsrep_commit(THD *thd, bool all)
if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_ws_handle.trx_id)
{
- WSREP_WARN("SQL statement was ineffective thd: %lld buf: %zu\n"
+ /*
+ Async replication slave may have applied some non-innodb workload,
+ and then has written replication "meta data" into gtid_slave_pos
+ innodb table. Writes to gtid_slave_pos must not be replicated,
+ but this activity has caused that innodb hton is registered for this
+ transaction, but no wsrep keys have been appended.
+ We enter in this code path, because IO cache has events for non-innodb
+ tables.
+ => we should not treat it an error if trx is not introduced for provider
+ */
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL)
+ {
+ WSREP_DEBUG("skipping wsrep replication for async slave, error not raised");
+ DBUG_RETURN(WSREP_TRX_OK);
+ }
+
+ WSREP_WARN("SQL statement was ineffective thd: %llu buf: %zu\n"
"schema: %s \n"
"QUERY: %s\n"
" => Skipping replication",
- (longlong) thd->thread_id, data_len,
+ (ulonglong) thd->thread_id, data_len,
(thd->db ? thd->db : "(null)"), thd->query());
+
rcode = WSREP_TRX_FAIL;
}
else if (!rcode)
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 5e2e48fd15d..062c9dcd74c 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -37,7 +37,6 @@
#include <cstdio>
#include <cstdlib>
#include "log_event.h"
-#include <slave.h>
#include "sql_plugin.h" /* wsrep_plugins_pre_init() */
#include <vector>
@@ -1544,6 +1543,39 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
{
return false;
}
+ /*
+ If mariadb master has replicated a CTAS, we should not replicate the create table
+ part separately as TOI, but to replicate both create table and following inserts
+ as one write set.
+ Howver, if CTAS creates empty table, we should replicate the create table alone
+ as TOI. We have to do relay log event lookup to see if row events follow the
+ create table event.
+ */
+ if (thd->slave_thread && !(thd->rgi_slave->gtid_ev_flags2 & Gtid_log_event::FL_STANDALONE))
+ {
+ /* this is CTAS, either empty or populated table */
+ ulonglong event_size = 0;
+ enum Log_event_type ev_type= wsrep_peak_event(thd->rgi_slave, &event_size);
+ switch (ev_type)
+ {
+ case QUERY_EVENT:
+ /* CTAS with empty table, we replicate create table as TOI */
+ break;
+
+ case TABLE_MAP_EVENT:
+ WSREP_DEBUG("replicating CTAS of empty table as TOI");
+ // fall through
+ case WRITE_ROWS_EVENT:
+ /* CTAS with populated table, we replicate later at commit time */
+ WSREP_DEBUG("skipping create table of CTAS replication");
+ return false;
+
+ default:
+ WSREP_WARN("unexpected async replication event: %d", ev_type);
+ }
+ return true;
+ }
+ /* no next async replication event */
return true;
case SQLCOM_CREATE_VIEW:
diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp
index 8e79aeac7ef..dacab3c485c 100644
--- a/storage/connect/inihandl.cpp
+++ b/storage/connect/inihandl.cpp
@@ -194,7 +194,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section )
}
for (key = section->key; key; key = key->next)
- if (key->name && key->name[0]) {
+ if (key->name[0]) {
fprintf(file, "%s", SVP(key->name));
if (key->value)
diff --git a/storage/innobase/os/os0thread.cc b/storage/innobase/os/os0thread.cc
index b34d875b759..2aac53f572d 100644
--- a/storage/innobase/os/os0thread.cc
+++ b/storage/innobase/os/os0thread.cc
@@ -125,11 +125,17 @@ os_thread_create_func(
pthread_attr_t attr;
- pthread_attr_init(&attr);
+ int ret = pthread_attr_init(&attr);
+ if (UNIV_UNLIKELY(ret)) {
+ fprintf(stderr,
+ "InnoDB: Error: pthread_attr_init() returned %d\n",
+ ret);
+ abort();
+ }
my_atomic_addlint(&os_thread_count, 1);
- int ret = pthread_create(&new_thread_id, &attr, func, arg);
+ ret = pthread_create(&new_thread_id, &attr, func, arg);
ut_a(ret == 0);