summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-09-24 15:32:39 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-09-24 15:32:39 +0300
commit79185bd0564794db91572c9d557b61fed143c6aa (patch)
tree1924273235f4dec40db4499d04a3e59b52a886de
parent359c286499e3d3bd82dd6b0d15f664d62f3e2f57 (diff)
parentd95361107c07b6e8257a7a82c41b18af64ab8d89 (diff)
downloadmariadb-git-79185bd0564794db91572c9d557b61fed143c6aa.tar.gz
Merge 10.6 into 10.7
-rw-r--r--CONTRIBUTING.md5
-rw-r--r--README.md3
-rw-r--r--cmake/cpack_rpm.cmake7
-rw-r--r--extra/mariabackup/datasink.cc8
-rw-r--r--extra/mariabackup/datasink.h1
-rw-r--r--extra/mariabackup/ds_archive.cc282
-rw-r--r--extra/mariabackup/ds_archive.h28
-rw-r--r--extra/mariabackup/ds_xbstream.cc14
m---------libmariadb0
-rw-r--r--libmysqld/libmysql.c12
-rw-r--r--man/mysqldump.110
-rw-r--r--mysql-test/main/alias.result12
-rw-r--r--mysql-test/main/alias.test2
-rw-r--r--mysql-test/main/mdev-504.result25
-rw-r--r--mysql-test/main/mdev-504.test82
-rw-r--r--mysql-test/suite/encryption/r/innodb_encryption.result2
-rw-r--r--mysql-test/suite/encryption/t/innodb_encryption.test2
-rw-r--r--mysql-test/suite/galera/r/galera_schema.result114
-rw-r--r--mysql-test/suite/galera/t/galera_schema.test61
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result4
-rw-r--r--mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result4
-rw-r--r--mysql-test/suite/galera_sr/r/GCF-627.result12
-rw-r--r--mysql-test/suite/galera_sr/t/GCF-627.test8
-rw-r--r--mysql-test/suite/innodb/r/innodb_defrag_stats.result122
-rw-r--r--mysql-test/suite/innodb/r/undo_truncate.result32
-rw-r--r--mysql-test/suite/innodb/t/innodb_defrag_stats.test99
-rw-r--r--mysql-test/suite/innodb/t/undo_truncate.opt1
-rw-r--r--mysql-test/suite/innodb/t/undo_truncate.test98
-rw-r--r--scripts/wsrep_sst_mariabackup.sh4
-rw-r--r--scripts/wsrep_sst_rsync.sh4
-rw-r--r--sql/CMakeLists.txt8
-rw-r--r--sql/gen_yy_files.cmake3
-rw-r--r--sql/sql_class.cc3
-rw-r--r--sql/sql_delete.cc10
-rw-r--r--sql/sql_update.cc11
-rw-r--r--sql/sql_yacc.yy3
-rw-r--r--sql/wsrep_schema.cc48
-rw-r--r--storage/innobase/btr/btr0defragment.cc1
-rw-r--r--storage/innobase/buf/buf0buf.cc1
-rw-r--r--storage/innobase/buf/buf0flu.cc6
-rw-r--r--storage/innobase/dict/dict0defrag_bg.cc31
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc2
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc54
-rw-r--r--storage/innobase/include/buf0buf.h2
-rw-r--r--storage/innobase/include/dict0defrag_bg.h8
-rw-r--r--storage/innobase/include/log0log.h16
-rw-r--r--storage/innobase/include/mtr0mtr.h4
-rw-r--r--storage/innobase/include/mtr0mtr.ic4
-rw-r--r--storage/innobase/include/sux_lock.h3
-rw-r--r--storage/innobase/include/trx0rseg.h2
-rw-r--r--storage/innobase/log/log0log.cc32
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc108
-rw-r--r--storage/innobase/row/row0ftsort.cc3
-rw-r--r--storage/innobase/srv/srv0srv.cc4
-rw-r--r--storage/innobase/sync/srw_lock.cc8
-rw-r--r--storage/innobase/trx/trx0purge.cc490
-rw-r--r--storage/innobase/trx/trx0rseg.cc10
-rw-r--r--storage/innobase/trx/trx0sys.cc4
-rw-r--r--storage/spider/mysql-test/spider/r/udf_pushdown.result218
-rw-r--r--storage/spider/mysql-test/spider/t/udf_pushdown.inc48
-rw-r--r--storage/spider/mysql-test/spider/t/udf_pushdown.test141
-rw-r--r--storage/spider/spd_db_mysql.cc6
-rw-r--r--storage/spider/spd_param.cc2
m---------wsrep-lib0
64 files changed, 1365 insertions, 987 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 64af450d29f..37899f37958 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,8 +8,7 @@ MariaDB Server has a vibrant community contributing in a wide range of areas. Th
- [maria-developers mailing list](http://launchpad.net/~maria-developers)
- [maria-discuss mailing list](http://launchpad.net/~maria-discuss)
- [maria-docs mailing list](http://launchpad.net/~maria-docs)
-- ircs://chat.freenode.net/maria ([see the IRC page on the Knowledge Base](https://mariadb.com/kb/en/meta/irc-chat-servers-and-zulip-instance/) for help with IRC).
-- The MariaDB Foundation and MariaDB Corporation have a presence on Reddit, Twitter, Facebook and Google Plus. See the [social media page](https://mariadb.com/kb/en/mariadb/social-media/).
+- The MariaDB Foundation and MariaDB Corporation have a presence on Reddit, Twitter and Facebook. See the [social media page](https://mariadb.com/kb/en/mariadb/social-media/).
### Help document MariaDB
----
@@ -36,7 +35,7 @@ You’re very welcome to support MariaDB Server as an individual, or talk your c
### Live QA for beginner contributors
----
-MariaDB has a dedicated time each week when we answer new contributor questions live on Zulip and IRC.
+MariaDB has a dedicated time each week when we answer new contributor questions live on Zulip.
From 8:00 to 10:00 UTC on Mondays, and 10:00 to 12:00 UTC on Thursdays, anyone can ask any questions they’d like,
and a live developer will be available to assist.
New contributors can ask questions any time, but we will provide immediate feedback during that interval.
diff --git a/README.md b/README.md
index f17a882d66e..58dbf105fb9 100644
--- a/README.md
+++ b/README.md
@@ -39,11 +39,10 @@ Help
More help is available from the Maria Discuss mailing list
https://launchpad.net/~maria-discuss, MariaDB's Zulip
instance, https://mariadb.zulipchat.com/
-and the #maria IRC channel on Freenode.
Live QA for beginner contributors
----
-MariaDB has a dedicated time each week when we answer new contributor questions live on Zulip and IRC.
+MariaDB has a dedicated time each week when we answer new contributor questions live on Zulip.
From 8:00 to 10:00 UTC on Mondays, and 10:00 to 12:00 UTC on Thursdays,
anyone can ask any questions they’d like, and a live developer will be available to assist.
diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake
index 5f954c7a1fe..bba9238664b 100644
--- a/cmake/cpack_rpm.cmake
+++ b/cmake/cpack_rpm.cmake
@@ -245,6 +245,7 @@ ELSEIF(RPM MATCHES "(rhel|centos)8")
ALTERNATIVE_NAME("server" "mariadb-server-utils")
ALTERNATIVE_NAME("shared" "mariadb-connector-c" ${MARIADB_CONNECTOR_C_VERSION}-1)
ALTERNATIVE_NAME("shared" "mariadb-connector-c-config" ${MARIADB_CONNECTOR_C_VERSION}-1)
+ ALTERNATIVE_NAME("devel" "mariadb-connector-c-devel" ${MARIADB_CONNECTOR_C_VERSION}-1)
SETA(CPACK_RPM_client_PACKAGE_PROVIDES "mariadb-galera = 3:%{version}-%{release}")
SETA(CPACK_RPM_common_PACKAGE_PROVIDES "mariadb-galera-common = 3:%{version}-%{release}")
SETA(CPACK_RPM_common_PACKAGE_REQUIRES "MariaDB-shared")
@@ -257,6 +258,12 @@ ELSEIF(RPM MATCHES "sles")
"mariadb-server = %{version}-%{release}"
)
ENDIF()
+
+# MDEV-24629, we need it outside of ELSIFs
+IF(RPM MATCHES "fedora3[234]")
+ ALTERNATIVE_NAME("common" "mariadb-connector-c-config" ${MARIADB_CONNECTOR_C_VERSION}-1)
+ENDIF()
+
SET(PYTHON_SHEBANG "/usr/bin/python3" CACHE STRING "python shebang")
# If we want to build build MariaDB-shared-compat,
diff --git a/extra/mariabackup/datasink.cc b/extra/mariabackup/datasink.cc
index 29bdc061014..a576526d7ff 100644
--- a/extra/mariabackup/datasink.cc
+++ b/extra/mariabackup/datasink.cc
@@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
#include "common.h"
#include "datasink.h"
#include "ds_compress.h"
-#include "ds_archive.h"
#include "ds_xbstream.h"
#include "ds_local.h"
#include "ds_stdout.h"
@@ -45,13 +44,6 @@ ds_create(const char *root, ds_type_t type)
case DS_TYPE_LOCAL:
ds = &datasink_local;
break;
- case DS_TYPE_ARCHIVE:
-#ifdef HAVE_LIBARCHIVE
- ds = &datasink_archive;
-#else
- die("mariabackup was built without libarchive support");
-#endif
- break;
case DS_TYPE_XBSTREAM:
ds = &datasink_xbstream;
break;
diff --git a/extra/mariabackup/datasink.h b/extra/mariabackup/datasink.h
index 5c82556b9ba..4bede4ec9e7 100644
--- a/extra/mariabackup/datasink.h
+++ b/extra/mariabackup/datasink.h
@@ -63,7 +63,6 @@ static inline int dummy_remove(const char *) {
typedef enum {
DS_TYPE_STDOUT,
DS_TYPE_LOCAL,
- DS_TYPE_ARCHIVE,
DS_TYPE_XBSTREAM,
DS_TYPE_COMPRESS,
DS_TYPE_ENCRYPT,
diff --git a/extra/mariabackup/ds_archive.cc b/extra/mariabackup/ds_archive.cc
deleted file mode 100644
index 3a5081119b3..00000000000
--- a/extra/mariabackup/ds_archive.cc
+++ /dev/null
@@ -1,282 +0,0 @@
-/******************************************************
-Copyright (c) 2013 Percona LLC and/or its affiliates.
-
-Streaming implementation for XtraBackup.
-
-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; version 2 of the License.
-
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*******************************************************/
-
-#include <my_global.h>
-#include <my_base.h>
-#include <archive.h>
-#include <archive_entry.h>
-#include "common.h"
-#include "datasink.h"
-
-#if ARCHIVE_VERSION_NUMBER < 3000000
-#define archive_write_add_filter_none(X) archive_write_set_compression_none(X)
-#define archive_write_free(X) archive_write_finish(X)
-#endif
-
-typedef struct {
- struct archive *archive;
- ds_file_t *dest_file;
- pthread_mutex_t mutex;
-} ds_archive_ctxt_t;
-
-typedef struct {
- struct archive_entry *entry;
- ds_archive_ctxt_t *archive_ctxt;
-} ds_archive_file_t;
-
-
-/***********************************************************************
-General archive interface */
-
-static ds_ctxt_t *archive_init(const char *root);
-static ds_file_t *archive_open(ds_ctxt_t *ctxt, const char *path,
- MY_STAT *mystat);
-static int archive_write(ds_file_t *file, const void *buf, size_t len);
-static int archive_close(ds_file_t *file);
-static void archive_deinit(ds_ctxt_t *ctxt);
-
-datasink_t datasink_archive = {
- &archive_init,
- &archive_open,
- &archive_write,
- &archive_close,
- &dummy_remove,
- &archive_deinit
-};
-
-static
-int
-my_archive_open_callback(struct archive *a __attribute__((unused)),
- void *data __attribute__((unused)))
-{
- return ARCHIVE_OK;
-}
-
-static
-ssize_t
-my_archive_write_callback(struct archive *a __attribute__((unused)),
- void *data, const void *buffer, size_t length)
-{
- ds_archive_ctxt_t *archive_ctxt;
-
- archive_ctxt = (ds_archive_ctxt_t *) data;
-
- xb_ad(archive_ctxt != NULL);
- xb_ad(archive_ctxt->dest_file != NULL);
-
- if (!ds_write(archive_ctxt->dest_file, buffer, length)) {
- return length;
- }
- return -1;
-}
-
-static
-int
-my_archive_close_callback(struct archive *a __attribute__((unused)),
- void *data __attribute__((unused)))
-{
- return ARCHIVE_OK;
-}
-
-static
-ds_ctxt_t *
-archive_init(const char *root __attribute__((unused)))
-{
- ds_ctxt_t *ctxt;
- ds_archive_ctxt_t *archive_ctxt;
- struct archive *a;
-
- ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_archive_ctxt_t),
- MYF(MY_FAE));
- archive_ctxt = (ds_archive_ctxt_t *)(ctxt + 1);
-
- if (pthread_mutex_init(&archive_ctxt->mutex, NULL)) {
- msg("archive_init: pthread_mutex_init() failed.\n");
- goto err;
- }
-
- a = archive_write_new();
- if (a == NULL) {
- msg("archive_write_new() failed.\n");
- goto err;
- }
-
- archive_ctxt->archive = a;
- archive_ctxt->dest_file = NULL;
-
- if(archive_write_add_filter_none(a) != ARCHIVE_OK ||
- archive_write_set_format_pax_restricted(a) != ARCHIVE_OK ||
- /* disable internal buffering so we don't have to flush the
- output in xtrabackup */
- archive_write_set_bytes_per_block(a, 0) != ARCHIVE_OK) {
- msg("failed to set libarchive archive options: %s\n",
- archive_error_string(a));
- archive_write_free(a);
- goto err;
- }
-
- if (archive_write_open(a, archive_ctxt, my_archive_open_callback,
- my_archive_write_callback,
- my_archive_close_callback) != ARCHIVE_OK) {
- msg("cannot open output archive.\n");
- return NULL;
- }
-
- ctxt->ptr = archive_ctxt;
-
- return ctxt;
-
-err:
- my_free(ctxt);
- return NULL;
-}
-
-static
-ds_file_t *
-archive_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
-{
- ds_archive_ctxt_t *archive_ctxt;
- ds_ctxt_t *dest_ctxt;
- ds_file_t *file;
- ds_archive_file_t *archive_file;
-
- struct archive *a;
- struct archive_entry *entry;
-
- xb_ad(ctxt->pipe_ctxt != NULL);
- dest_ctxt = ctxt->pipe_ctxt;
-
- archive_ctxt = (ds_archive_ctxt_t *) ctxt->ptr;
-
- pthread_mutex_lock(&archive_ctxt->mutex);
- if (archive_ctxt->dest_file == NULL) {
- archive_ctxt->dest_file = ds_open(dest_ctxt, path, mystat);
- if (archive_ctxt->dest_file == NULL) {
- return NULL;
- }
- }
- pthread_mutex_unlock(&archive_ctxt->mutex);
-
- file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
- sizeof(ds_archive_file_t),
- MYF(MY_FAE));
-
- archive_file = (ds_archive_file_t *) (file + 1);
-
- a = archive_ctxt->archive;
-
- entry = archive_entry_new();
- if (entry == NULL) {
- msg("archive_entry_new() failed.\n");
- goto err;
- }
-
- archive_entry_set_size(entry, mystat->st_size);
- archive_entry_set_mode(entry, 0660);
- archive_entry_set_filetype(entry, AE_IFREG);
- archive_entry_set_pathname(entry, path);
- archive_entry_set_mtime(entry, mystat->st_mtime, 0);
-
- archive_file->entry = entry;
- archive_file->archive_ctxt = archive_ctxt;
-
- if (archive_write_header(a, entry) != ARCHIVE_OK) {
- msg("archive_write_header() failed.\n");
- archive_entry_free(entry);
- goto err;
- }
-
- file->ptr = archive_file;
- file->path = archive_ctxt->dest_file->path;
-
- return file;
-
-err:
- if (archive_ctxt->dest_file) {
- ds_close(archive_ctxt->dest_file);
- archive_ctxt->dest_file = NULL;
- }
- my_free(file);
-
- return NULL;
-}
-
-static
-int
-archive_write(ds_file_t *file, const void *buf, size_t len)
-{
- ds_archive_file_t *archive_file;
- struct archive *a;
-
- archive_file = (ds_archive_file_t *) file->ptr;
-
- a = archive_file->archive_ctxt->archive;
-
- xb_ad(archive_file->archive_ctxt->dest_file != NULL);
- if (archive_write_data(a, buf, len) < 0) {
- msg("archive_write_data() failed: %s (errno = %d)\n",
- archive_error_string(a), archive_errno(a));
- return 1;
- }
-
- return 0;
-}
-
-static
-int
-archive_close(ds_file_t *file)
-{
- ds_archive_file_t *archive_file;
- int rc = 0;
-
- archive_file = (ds_archive_file_t *)file->ptr;
-
- archive_entry_free(archive_file->entry);
-
- my_free(file);
-
- return rc;
-}
-
-static
-void
-archive_deinit(ds_ctxt_t *ctxt)
-{
- struct archive *a;
- ds_archive_ctxt_t *archive_ctxt;
-
- archive_ctxt = (ds_archive_ctxt_t *) ctxt->ptr;
-
- a = archive_ctxt->archive;
-
- if (archive_write_close(a) != ARCHIVE_OK) {
- msg("archive_write_close() failed.\n");
- }
- archive_write_free(a);
-
- if (archive_ctxt->dest_file) {
- ds_close(archive_ctxt->dest_file);
- archive_ctxt->dest_file = NULL;
- }
-
- pthread_mutex_destroy(&archive_ctxt->mutex);
-
- my_free(ctxt);
-}
diff --git a/extra/mariabackup/ds_archive.h b/extra/mariabackup/ds_archive.h
deleted file mode 100644
index f419fca0c9f..00000000000
--- a/extra/mariabackup/ds_archive.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/******************************************************
-Copyright (c) 2013 Percona LLC and/or its affiliates.
-
-Streaming interface for XtraBackup.
-
-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; version 2 of the License.
-
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*******************************************************/
-
-#ifndef DS_ARCHIVE_H
-#define DS_ARCHIVE_H
-
-#include "datasink.h"
-
-extern datasink_t datasink_archive;
-
-#endif
diff --git a/extra/mariabackup/ds_xbstream.cc b/extra/mariabackup/ds_xbstream.cc
index 4d165ad11d9..3bf8bd086c2 100644
--- a/extra/mariabackup/ds_xbstream.cc
+++ b/extra/mariabackup/ds_xbstream.cc
@@ -126,14 +126,20 @@ xbstream_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
pthread_mutex_lock(&stream_ctxt->mutex);
if (stream_ctxt->dest_file == NULL) {
stream_ctxt->dest_file = ds_open(dest_ctxt, path, mystat);
- if (stream_ctxt->dest_file == NULL) {
- return NULL;
- }
}
pthread_mutex_unlock(&stream_ctxt->mutex);
+ if (stream_ctxt->dest_file == NULL) {
+ return NULL;
+ }
file = (ds_file_t *) my_malloc(PSI_NOT_INSTRUMENTED,
- sizeof(ds_file_t) + sizeof(ds_stream_file_t), MYF(MY_FAE));
+ sizeof(ds_file_t) +
+ sizeof(ds_stream_file_t),
+ MYF(MY_FAE));
+ if (!file) {
+ msg("my_malloc() failed.");
+ goto err;
+ }
stream_file = (ds_stream_file_t *) (file + 1);
xbstream = stream_ctxt->xbstream;
diff --git a/libmariadb b/libmariadb
-Subproject 2ca0c22fd36c1b34115352e22c5f6b7d23c2c04
+Subproject ffa3451fa511ad27164356bd8c620032eba6551
diff --git a/libmysqld/libmysql.c b/libmysqld/libmysql.c
index 7a0843d32e5..6c7e0b3b812 100644
--- a/libmysqld/libmysql.c
+++ b/libmysqld/libmysql.c
@@ -3966,6 +3966,7 @@ static my_bool is_binary_compatible(enum enum_field_types type1,
static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
{
+ my_bool field_is_unsigned;
DBUG_ENTER("setup_one_fetch_function");
/* Setup data copy functions for the different supported types */
@@ -4042,6 +4043,7 @@ static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
/* Setup skip_result functions (to calculate max_length) */
param->skip_result= skip_result_fixed;
+ field_is_unsigned= MY_TEST(field->flags & UNSIGNED_FLAG);
switch (field->type) {
case MYSQL_TYPE_NULL: /* for dummy binds */
param->pack_length= 0;
@@ -4049,23 +4051,23 @@ static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
break;
case MYSQL_TYPE_TINY:
param->pack_length= 1;
- field->max_length= 4; /* as in '-127' */
+ field->max_length= field_is_unsigned ? 3 : 4; /* '255' and '-127' */
break;
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_SHORT:
param->pack_length= 2;
- field->max_length= 6; /* as in '-32767' */
+ field->max_length= field_is_unsigned ? 5 : 6; /* 65536 and '-32767' */
break;
case MYSQL_TYPE_INT24:
- field->max_length= 9; /* as in '16777216' or in '-8388607' */
+ field->max_length= 8; /* '16777216' or in '-8388607' */
param->pack_length= 4;
break;
case MYSQL_TYPE_LONG:
- field->max_length= 11; /* '-2147483647' */
+ field->max_length= field_is_unsigned ? 10 : 11; /* '4294967295' and '-2147483647' */
param->pack_length= 4;
break;
case MYSQL_TYPE_LONGLONG:
- field->max_length= 21; /* '18446744073709551616' */
+ field->max_length= 20; /* '18446744073709551616' or -9223372036854775808 */
param->pack_length= 8;
break;
case MYSQL_TYPE_FLOAT:
diff --git a/man/mysqldump.1 b/man/mysqldump.1
index e3206e612f7..ad4b167c7b8 100644
--- a/man/mysqldump.1
+++ b/man/mysqldump.1
@@ -2279,7 +2279,7 @@ servers \- remote (federated) servers as \fBCREATE SERVER\fR\&.
.sp -1
.IP \(bu 2.3
.\}
-stats \- statistics tables, InnoDB and Engine Independent Table Statistics (EITS), are dumped as \fBREPLACE INTO\fR (or \fBINSERT IGNORE\fR if \fB\-\-insert\-into\fR is specified) statements without (re)creating tables\&.
+stats \- statistics tables, InnoDB and Engine Independent Table Statistics (EITS), are dumped as \fBREPLACE INTO\fR (or \fBINSERT IGNORE\fR if \fB\-\-insert\-ignore\fR is specified) statements without (re)creating tables\&.
.RE
.RS 4
.ie n \{\
@@ -2289,17 +2289,17 @@ stats \- statistics tables, InnoDB and Engine Independent Table Statistics (EITS
.sp -1
.IP \(bu 2.3
.\}
-timezones \- timezone related system tables dumped as \fBREPLACE INTO\fR (or \fBINSERT IGNORE\fR if \fB\-\-insert\-into\fR is specified) statements without (re)creating tables\&.
+timezones \- timezone related system tables dumped as \fBREPLACE INTO\fR (or \fBINSERT IGNORE\fR if \fB\-\-insert\-ignore\fR is specified) statements without (re)creating tables\&.
.RE
.sp
-The format of the output is affected by \fB\-\-replace\fR and \fB\-\-insert\-into\fR\&. The \fB\-\-replace\fR option will output \fBCREATE OR REPLACE\fR
+The format of the output is affected by \fB\-\-replace\fR and \fB\-\-insert\-ignore\fR\&. The \fB\-\-replace\fR option will output \fBCREATE OR REPLACE\fR
forms of SQL, and also \fBDROP IF EXISTS\fR prior to \fBCREATE\fR, if a \fBCREATE OR REPLACE\fR option isn't available.
.sp
With \fB\-\-system=user\fR (or \fBall\fR), and \fB\-\-replace\fR, SQL is generated to generate an error if attempting to import the dump with a connection user that is being replaced within the dump\&.
.sp
-The \fB\-\-insert\-into\fR option will cause \fBCREATE IF NOT EXIST\fR forms of SQL to generated if available.
+The \fB\-\-insert\-ignore\fR option will cause \fBCREATE IF NOT EXIST\fR forms of SQL to generated if available.
.sp
-For stats, and timezones, \fB\-\-replace\fR and \fB\-\-insert\-into\fR have the usual effects.
+For stats, and timezones, \fB\-\-replace\fR and \fB\-\-insert\-ignore\fR have the usual effects.
.sp
Enabling specific options here will cause the relevant tables in the mysql database to be ignored when dumping the mysql database or \fB\-\-all\-databases\fR\&.
.sp
diff --git a/mysql-test/main/alias.result b/mysql-test/main/alias.result
index 0d14607f613..266991afbec 100644
--- a/mysql-test/main/alias.result
+++ b/mysql-test/main/alias.result
@@ -223,16 +223,16 @@ disconnect c1;
#
create or replace table t1 (a int);
create or replace table t2 (b int);
-insert into t1 values(1<<30),(1<<29);
+insert into t1 values(111111111),(-2147483648);
insert into t2 values(1),(2);
select t1.a as a1 from t1 as t1,t2 order by t2.b,t1.a;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def test t1 t1 a a1 3 11 10 Y 32768 0 63
+def test t1 t1 a a1 3 11 11 Y 32768 0 63
a1
-536870912
-1073741824
-536870912
-1073741824
+-2147483648
+111111111
+-2147483648
+111111111
drop table t1,t2;
#
# End of 10.4 tests
diff --git a/mysql-test/main/alias.test b/mysql-test/main/alias.test
index 2408509ba10..881cc34d6c6 100644
--- a/mysql-test/main/alias.test
+++ b/mysql-test/main/alias.test
@@ -231,7 +231,7 @@ disconnect c1;
--echo #
create or replace table t1 (a int);
create or replace table t2 (b int);
-insert into t1 values(1<<30),(1<<29);
+insert into t1 values(111111111),(-2147483648);
insert into t2 values(1),(2);
--enable_metadata
select t1.a as a1 from t1 as t1,t2 order by t2.b,t1.a;
diff --git a/mysql-test/main/mdev-504.result b/mysql-test/main/mdev-504.result
deleted file mode 100644
index e34e57be6ed..00000000000
--- a/mysql-test/main/mdev-504.result
+++ /dev/null
@@ -1,25 +0,0 @@
-set @save_use_stat_tables=@@global.use_stat_tables;
-SET GLOBAL net_write_timeout = 900;
-CREATE TABLE A (
-pk INTEGER AUTO_INCREMENT PRIMARY KEY,
-fdate DATE
-) ENGINE=MyISAM;
-CREATE PROCEDURE p_analyze()
-BEGIN
-DECLARE attempts INTEGER DEFAULT 100;
-wl_loop: WHILE attempts > 0 DO
-ANALYZE TABLE A;
-SET attempts = attempts - 1;
-END WHILE wl_loop;
-END |
-CREATE FUNCTION rnd3() RETURNS INT
-BEGIN
-RETURN ROUND(3 * RAND() + 0.5);
-END |
-SET GLOBAL use_stat_tables = PREFERABLY;
-connection default;
-DROP TABLE A;
-DROP PROCEDURE p_analyze;
-DROP FUNCTION rnd3;
-SET GLOBAL use_stat_tables = @save_use_stat_tables;
-SET GLOBAL net_write_timeout = DEFAULT;
diff --git a/mysql-test/main/mdev-504.test b/mysql-test/main/mdev-504.test
deleted file mode 100644
index 277b5a038a0..00000000000
--- a/mysql-test/main/mdev-504.test
+++ /dev/null
@@ -1,82 +0,0 @@
---source include/not_valgrind.inc
---source include/no_protocol.inc
-
-set @save_use_stat_tables=@@global.use_stat_tables;
-
-SET GLOBAL net_write_timeout = 900;
-
-CREATE TABLE A (
- pk INTEGER AUTO_INCREMENT PRIMARY KEY,
- fdate DATE
-) ENGINE=MyISAM;
-
---delimiter |
-
-CREATE PROCEDURE p_analyze()
-BEGIN
- DECLARE attempts INTEGER DEFAULT 100;
- wl_loop: WHILE attempts > 0 DO
- ANALYZE TABLE A;
- SET attempts = attempts - 1;
- END WHILE wl_loop;
-END |
-
-CREATE FUNCTION rnd3() RETURNS INT
-BEGIN
- RETURN ROUND(3 * RAND() + 0.5);
-END |
-
---delimiter ;
-
-SET GLOBAL use_stat_tables = PREFERABLY;
-
---let $trial = 100
-
---disable_query_log
---disable_result_log
---disable_warnings
-while ($trial)
-{
-
- --connect (con1,localhost,root,,)
- --send CALL p_analyze()
-
- --connect (con2,localhost,root,,)
- --send CALL p_analyze()
-
- --let $run = 100
-
- while ($run)
- {
- --connect (con3,localhost,root,,)
-
- let $query = `SELECT CASE rnd3()
- WHEN 1 THEN 'INSERT INTO A (pk) VALUES (NULL)'
- WHEN 2 THEN 'DELETE FROM A LIMIT 1'
- ELSE 'UPDATE IGNORE A SET fdate = 2 LIMIT 1' END`;
- --eval $query
- --disconnect con3
- --dec $run
- }
-
- --connection con2
- --reap
- --disconnect con2
- --connection con1
- --reap
- --disconnect con1
-
- --dec $trial
-}
-
---enable_query_log
---enable_result_log
---enable_warnings
-
-# Cleanup
---connection default
-DROP TABLE A;
-DROP PROCEDURE p_analyze;
-DROP FUNCTION rnd3;
-SET GLOBAL use_stat_tables = @save_use_stat_tables;
-SET GLOBAL net_write_timeout = DEFAULT;
diff --git a/mysql-test/suite/encryption/r/innodb_encryption.result b/mysql-test/suite/encryption/r/innodb_encryption.result
index 4ede82ebd38..3b1552be4be 100644
--- a/mysql-test/suite/encryption/r/innodb_encryption.result
+++ b/mysql-test/suite/encryption/r/innodb_encryption.result
@@ -19,7 +19,7 @@ innodb_system
# Success!
# Now turn off encryption and wait for threads to decrypt everything
SET GLOBAL innodb_encrypt_tables = off;
-# Wait max 10 min for key encryption threads to encrypt all spaces
+# Wait max 10 min for key encryption threads to decrypt all spaces
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0
AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NAME NOT LIKE 'mysql/transaction_registry';
NAME
diff --git a/mysql-test/suite/encryption/t/innodb_encryption.test b/mysql-test/suite/encryption/t/innodb_encryption.test
index 1c8d200458a..2b0b2b8d7fb 100644
--- a/mysql-test/suite/encryption/t/innodb_encryption.test
+++ b/mysql-test/suite/encryption/t/innodb_encryption.test
@@ -33,7 +33,7 @@ AND NAME NOT LIKE 'innodb_undo%' AND NAME NOT LIKE 'mysql/innodb_%_stats' AND NA
--echo # Now turn off encryption and wait for threads to decrypt everything
SET GLOBAL innodb_encrypt_tables = off;
---echo # Wait max 10 min for key encryption threads to encrypt all spaces
+--echo # Wait max 10 min for key encryption threads to decrypt all spaces
--let $wait_timeout= 600
--let $wait_condition=SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
--source include/wait_condition.inc
diff --git a/mysql-test/suite/galera/r/galera_schema.result b/mysql-test/suite/galera/r/galera_schema.result
new file mode 100644
index 00000000000..24a4099c94d
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_schema.result
@@ -0,0 +1,114 @@
+connection node_2;
+connection node_1;
+CREATE TABLE IF NOT EXISTS wsrep_cluster
+(
+cluster_uuid CHAR(36) PRIMARY KEY,
+view_id BIGINT NOT NULL,
+view_seqno BIGINT NOT NULL,
+protocol_version INT NOT NULL,
+capabilities INT NOT NULL
+) ENGINE=InnoDB;
+CREATE TABLE IF NOT EXISTS wsrep_cluster_members
+(
+node_uuid CHAR(36) PRIMARY KEY,
+cluster_uuid CHAR(36) NOT NULL,
+node_name CHAR(32) NOT NULL,
+node_incoming_address VARCHAR(256) NOT NULL
+) ENGINE=InnoDB;
+CREATE TABLE IF NOT EXISTS wsrep_cluster_members_history
+(
+node_uuid CHAR(36) PRIMARY KEY,
+cluster_uuid CHAR(36) NOT NULL,
+last_view_id BIGINT NOT NULL,
+last_view_seqno BIGINT NOT NULL,
+node_name CHAR(32) NOT NULL,
+node_incoming_address VARCHAR(256) NOT NULL
+) ENGINE=InnoDB;
+CREATE TABLE IF NOT EXISTS wsrep_streaming_log
+(
+node_uuid CHAR(36),
+trx_id BIGINT,
+seqno BIGINT,
+flags INT NOT NULL,
+frag LONGBLOB NOT NULL,
+PRIMARY KEY (node_uuid, trx_id, seqno)
+) ENGINE=InnoDB;
+DELETE FROM wsrep_cluster;
+DELETE FROM wsrep_cluster_members;
+ALTER TABLE wsrep_cluster STATS_PERSISTENT=0;
+ALTER TABLE wsrep_cluster_members STATS_PERSISTENT=0;
+ALTER TABLE wsrep_cluster_members_history STATS_PERSISTENT=0;
+ALTER TABLE wsrep_streaming_log STATS_PERSISTENT=0;
+SHOW CREATE TABLE wsrep_cluster;
+Table Create Table
+wsrep_cluster CREATE TABLE `wsrep_cluster` (
+ `cluster_uuid` char(36) NOT NULL,
+ `view_id` bigint(20) NOT NULL,
+ `view_seqno` bigint(20) NOT NULL,
+ `protocol_version` int(11) NOT NULL,
+ `capabilities` int(11) NOT NULL,
+ PRIMARY KEY (`cluster_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
+SHOW CREATE TABLE wsrep_cluster_members;
+Table Create Table
+wsrep_cluster_members CREATE TABLE `wsrep_cluster_members` (
+ `node_uuid` char(36) NOT NULL,
+ `cluster_uuid` char(36) NOT NULL,
+ `node_name` char(32) NOT NULL,
+ `node_incoming_address` varchar(256) NOT NULL,
+ PRIMARY KEY (`node_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
+SHOW CREATE TABLE wsrep_cluster_members_history;
+Table Create Table
+wsrep_cluster_members_history CREATE TABLE `wsrep_cluster_members_history` (
+ `node_uuid` char(36) NOT NULL,
+ `cluster_uuid` char(36) NOT NULL,
+ `last_view_id` bigint(20) NOT NULL,
+ `last_view_seqno` bigint(20) NOT NULL,
+ `node_name` char(32) NOT NULL,
+ `node_incoming_address` varchar(256) NOT NULL,
+ PRIMARY KEY (`node_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
+SHOW CREATE TABLE wsrep_streaming_log;
+Table Create Table
+wsrep_streaming_log CREATE TABLE `wsrep_streaming_log` (
+ `node_uuid` char(36) NOT NULL,
+ `trx_id` bigint(20) NOT NULL,
+ `seqno` bigint(20) NOT NULL,
+ `flags` int(11) NOT NULL,
+ `frag` longblob NOT NULL,
+ PRIMARY KEY (`node_uuid`,`trx_id`,`seqno`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
+SHOW CREATE TABLE mysql.wsrep_cluster;
+Table Create Table
+wsrep_cluster CREATE TABLE `wsrep_cluster` (
+ `cluster_uuid` char(36) NOT NULL,
+ `view_id` bigint(20) NOT NULL,
+ `view_seqno` bigint(20) NOT NULL,
+ `protocol_version` int(11) NOT NULL,
+ `capabilities` int(11) NOT NULL,
+ PRIMARY KEY (`cluster_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
+SHOW CREATE TABLE mysql.wsrep_cluster_members;
+Table Create Table
+wsrep_cluster_members CREATE TABLE `wsrep_cluster_members` (
+ `node_uuid` char(36) NOT NULL,
+ `cluster_uuid` char(36) NOT NULL,
+ `node_name` char(32) NOT NULL,
+ `node_incoming_address` varchar(256) NOT NULL,
+ PRIMARY KEY (`node_uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
+SHOW CREATE TABLE mysql.wsrep_streaming_log;
+Table Create Table
+wsrep_streaming_log CREATE TABLE `wsrep_streaming_log` (
+ `node_uuid` char(36) NOT NULL,
+ `trx_id` bigint(20) NOT NULL,
+ `seqno` bigint(20) NOT NULL,
+ `flags` int(11) NOT NULL,
+ `frag` longblob NOT NULL,
+ PRIMARY KEY (`node_uuid`,`trx_id`,`seqno`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
+DROP TABLE wsrep_cluster;
+DROP TABLE wsrep_cluster_members;
+DROP TABLE wsrep_cluster_members_history;
+DROP TABLE wsrep_streaming_log;
diff --git a/mysql-test/suite/galera/t/galera_schema.test b/mysql-test/suite/galera/t/galera_schema.test
new file mode 100644
index 00000000000..a3ee814c393
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_schema.test
@@ -0,0 +1,61 @@
+--source include/galera_cluster.inc
+
+CREATE TABLE IF NOT EXISTS wsrep_cluster
+(
+ cluster_uuid CHAR(36) PRIMARY KEY,
+ view_id BIGINT NOT NULL,
+ view_seqno BIGINT NOT NULL,
+ protocol_version INT NOT NULL,
+ capabilities INT NOT NULL
+) ENGINE=InnoDB;
+
+CREATE TABLE IF NOT EXISTS wsrep_cluster_members
+(
+ node_uuid CHAR(36) PRIMARY KEY,
+ cluster_uuid CHAR(36) NOT NULL,
+ node_name CHAR(32) NOT NULL,
+ node_incoming_address VARCHAR(256) NOT NULL
+) ENGINE=InnoDB;
+
+CREATE TABLE IF NOT EXISTS wsrep_cluster_members_history
+(
+ node_uuid CHAR(36) PRIMARY KEY,
+ cluster_uuid CHAR(36) NOT NULL,
+ last_view_id BIGINT NOT NULL,
+ last_view_seqno BIGINT NOT NULL,
+ node_name CHAR(32) NOT NULL,
+ node_incoming_address VARCHAR(256) NOT NULL
+) ENGINE=InnoDB;
+
+CREATE TABLE IF NOT EXISTS wsrep_streaming_log
+(
+ node_uuid CHAR(36),
+ trx_id BIGINT,
+ seqno BIGINT,
+ flags INT NOT NULL,
+ frag LONGBLOB NOT NULL,
+ PRIMARY KEY (node_uuid, trx_id, seqno)
+) ENGINE=InnoDB;
+
+DELETE FROM wsrep_cluster;
+DELETE FROM wsrep_cluster_members;
+
+ALTER TABLE wsrep_cluster STATS_PERSISTENT=0;
+ALTER TABLE wsrep_cluster_members STATS_PERSISTENT=0;
+ALTER TABLE wsrep_cluster_members_history STATS_PERSISTENT=0;
+ALTER TABLE wsrep_streaming_log STATS_PERSISTENT=0;
+
+SHOW CREATE TABLE wsrep_cluster;
+SHOW CREATE TABLE wsrep_cluster_members;
+SHOW CREATE TABLE wsrep_cluster_members_history;
+SHOW CREATE TABLE wsrep_streaming_log;
+
+SHOW CREATE TABLE mysql.wsrep_cluster;
+SHOW CREATE TABLE mysql.wsrep_cluster_members;
+#SHOW CREATE TABLE mysql.wsrep_cluster_members_history;
+SHOW CREATE TABLE mysql.wsrep_streaming_log;
+
+DROP TABLE wsrep_cluster;
+DROP TABLE wsrep_cluster_members;
+DROP TABLE wsrep_cluster_members_history;
+DROP TABLE wsrep_streaming_log;
diff --git a/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result
index ba01eab0e26..f51eb815cd5 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result
@@ -14,7 +14,7 @@ wsrep_cluster CREATE TABLE `wsrep_cluster` (
`protocol_version` int(11) NOT NULL,
`capabilities` int(11) NOT NULL,
PRIMARY KEY (`cluster_uuid`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
SHOW CREATE TABLE mysql.wsrep_cluster_members;
Table Create Table
wsrep_cluster_members CREATE TABLE `wsrep_cluster_members` (
@@ -23,7 +23,7 @@ wsrep_cluster_members CREATE TABLE `wsrep_cluster_members` (
`node_name` char(32) NOT NULL,
`node_incoming_address` varchar(256) NOT NULL,
PRIMARY KEY (`node_uuid`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_cluster;
EXPECT_1
1
diff --git a/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result
index 2a29afd62be..d9d3e817bed 100644
--- a/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result
+++ b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result
@@ -14,7 +14,7 @@ wsrep_cluster CREATE TABLE `wsrep_cluster` (
`protocol_version` int(11) NOT NULL,
`capabilities` int(11) NOT NULL,
PRIMARY KEY (`cluster_uuid`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
SHOW CREATE TABLE mysql.wsrep_cluster_members;
Table Create Table
wsrep_cluster_members CREATE TABLE `wsrep_cluster_members` (
@@ -23,7 +23,7 @@ wsrep_cluster_members CREATE TABLE `wsrep_cluster_members` (
`node_name` char(32) NOT NULL,
`node_incoming_address` varchar(256) NOT NULL,
PRIMARY KEY (`node_uuid`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0
SELECT @@sql_safe_updates;
@@sql_safe_updates
1
diff --git a/mysql-test/suite/galera_sr/r/GCF-627.result b/mysql-test/suite/galera_sr/r/GCF-627.result
index 65d8c95ad08..7cd2ab63ff3 100644
--- a/mysql-test/suite/galera_sr/r/GCF-627.result
+++ b/mysql-test/suite/galera_sr/r/GCF-627.result
@@ -2,7 +2,6 @@ connection node_2;
connection node_1;
connection node_1;
CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
-CREATE TABLE t2 (f1 INTEGER);
SET SESSION wsrep_trx_fragment_size = 1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
@@ -16,9 +15,10 @@ connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
INSERT INTO t1 VALUES (2);
ERROR 42S02: Table 'test.t1' doesn't exist
connection node_1;
-SELECT * FROM mysql.wsrep_streaming_log;
-node_uuid trx_id seqno flags frag
+SELECT COUNT(*) FROM mysql.wsrep_streaming_log;
+COUNT(*)
+0
connection node_2;
-SELECT * FROM mysql.wsrep_streaming_log;
-node_uuid trx_id seqno flags frag
-DROP TABLE t2;
+SELECT COUNT(*) FROM mysql.wsrep_streaming_log;
+COUNT(*)
+0
diff --git a/mysql-test/suite/galera_sr/t/GCF-627.test b/mysql-test/suite/galera_sr/t/GCF-627.test
index ad351eb9da6..6990c12314d 100644
--- a/mysql-test/suite/galera_sr/t/GCF-627.test
+++ b/mysql-test/suite/galera_sr/t/GCF-627.test
@@ -1,9 +1,7 @@
--source include/galera_cluster.inc
---source include/have_innodb.inc
--connection node_1
CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB;
-CREATE TABLE t2 (f1 INTEGER);
SET SESSION wsrep_trx_fragment_size = 1;
SET AUTOCOMMIT=OFF;
@@ -25,11 +23,9 @@ INSERT INTO t1 VALUES (2);
--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
--source include/wait_condition.inc
-SELECT * FROM mysql.wsrep_streaming_log;
+SELECT COUNT(*) FROM mysql.wsrep_streaming_log;
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
--source include/wait_condition.inc
-SELECT * FROM mysql.wsrep_streaming_log;
-
-DROP TABLE t2;
+SELECT COUNT(*) FROM mysql.wsrep_streaming_log;
diff --git a/mysql-test/suite/innodb/r/innodb_defrag_stats.result b/mysql-test/suite/innodb/r/innodb_defrag_stats.result
index 4fdcf42faa1..2e7a2ba5197 100644
--- a/mysql-test/suite/innodb/r/innodb_defrag_stats.result
+++ b/mysql-test/suite/innodb/r/innodb_defrag_stats.result
@@ -1,25 +1,32 @@
-select @@global.innodb_stats_persistent;
-@@global.innodb_stats_persistent
-1
-set global innodb_defragment_stats_accuracy = 20;
-CREATE TABLE t1(a INT PRIMARY KEY, b VARCHAR(256), KEY SECOND(a, b))
-ENGINE=INNODB;
+SET GLOBAL innodb_defragment_stats_accuracy = 20;
+DELETE FROM mysql.innodb_index_stats;
+# Create table.
+CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256),
+KEY SECOND(a, b)) ENGINE=INNODB STATS_PERSISTENT=0;
INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_1_to_1024;
# Not enough page splits to trigger persistent stats write yet.
-select * from mysql.innodb_index_stats where table_name='t1'
-and stat_name in ('n_page_split','n_pages_freed,n_leaf_pages_defrag');
-database_name table_name index_name last_update stat_name stat_value sample_size stat_description
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+count(stat_value) = 0
+1
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+count(stat_value) = 0
+1
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
+count(stat_value) = 0
+1
INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_1025_to_2048;
# Persistent stats recorded.
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
count(stat_value) > 0
1
-select * from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
-database_name table_name index_name last_update stat_name stat_value sample_size stat_description
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+count(stat_value) = 0
+1
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
count(stat_value) > 0
1
# Delete some rows.
+BEGIN;
delete from t1 where a between 100 * 20 and 100 * 20 + 30;
delete from t1 where a between 100 * 19 and 100 * 19 + 30;
delete from t1 where a between 100 * 18 and 100 * 18 + 30;
@@ -40,82 +47,93 @@ delete from t1 where a between 100 * 4 and 100 * 4 + 30;
delete from t1 where a between 100 * 3 and 100 * 3 + 30;
delete from t1 where a between 100 * 2 and 100 * 2 + 30;
delete from t1 where a between 100 * 1 and 100 * 1 + 30;
-# restart
-# Server Restarted
-# Confirm persistent stats still there after restart.
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
+COMMIT;
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
count(stat_value) > 0
1
-select * from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
-database_name table_name index_name last_update stat_name stat_value sample_size stat_description
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+count(stat_value) = 0
+1
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
count(stat_value) > 0
1
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
-select sleep(2);
-sleep(2)
-0
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
count(stat_value) > 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
count(stat_value) > 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
count(stat_value) > 0
1
set global innodb_defragment_stats_accuracy = 40;
-INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_2049_to_4096;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
+INSERT INTO t1 (b) SELECT b from t1;
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
count(stat_value) > 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
count(stat_value) > 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
count(stat_value) > 0
1
-INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_4097_to_8192;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
+INSERT INTO t1 (b) SELECT b from t1;
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
count(stat_value) > 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
count(stat_value) > 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
count(stat_value) > 0
1
# Table rename should cause stats rename.
rename table t1 to t2;
-select * from mysql.innodb_index_stats where table_name = 't1';
-database_name table_name index_name last_update stat_name stat_value sample_size stat_description
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_page_split');
-count(stat_value) > 0
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+count(stat_value) = 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_pages_freed');
-count(stat_value) > 0
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+count(stat_value) = 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) > 0
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
+count(stat_value) = 0
1
-# Drop index should cause stats drop.
-drop index SECOND on t2;
-select * from mysql.innodb_index_stats where table_name = 't2' and index_name = 'SECOND';
-database_name table_name index_name last_update stat_name stat_value sample_size stat_description
-# restart
-Server Restarted
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_page_split');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_page_split');
count(stat_value) > 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed');
count(stat_value) > 0
1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_leaf_pages_defrag');
count(stat_value) > 0
1
+# Drop index should cause stats drop, but will not.
+drop index SECOND on t2;
+SELECT stat_name, stat_value>0 FROM mysql.innodb_index_stats
+WHERE table_name like '%t2%' AND index_name='SECOND';
+stat_name stat_value>0
+#
+# MDEV-26636: Statistics must not be written for temporary tables
+#
+SET GLOBAL innodb_defragment_stats_accuracy = 1;
+CREATE TEMPORARY TABLE t (a INT PRIMARY KEY, c CHAR(255) NOT NULL)
+ENGINE=InnoDB;
+INSERT INTO t SELECT seq, '' FROM seq_1_to_100;
+# restart
+SELECT * FROM mysql.innodb_index_stats where table_name like '%t1%';
+database_name table_name index_name last_update stat_name stat_value sample_size stat_description
+SELECT table_name, index_name, stat_name, stat_value>0
+FROM mysql.innodb_index_stats;
+table_name index_name stat_name stat_value>0
+t2 PRIMARY n_leaf_pages_defrag 1
+t2 PRIMARY n_leaf_pages_reserved 1
+t2 PRIMARY n_page_split 1
+t2 PRIMARY n_pages_freed 0
# Clean up
+ALTER TABLE t2 STATS_PERSISTENT=1;
DROP TABLE t2;
-select * from mysql.innodb_index_stats where table_name = 't2';
+SELECT * FROM mysql.innodb_index_stats;
database_name table_name index_name last_update stat_name stat_value sample_size stat_description
diff --git a/mysql-test/suite/innodb/r/undo_truncate.result b/mysql-test/suite/innodb/r/undo_truncate.result
index ad236bdecd4..fbfd061c9cc 100644
--- a/mysql-test/suite/innodb/r/undo_truncate.result
+++ b/mysql-test/suite/innodb/r/undo_truncate.result
@@ -1,34 +1,13 @@
-SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
-SET @save_truncate = @@GLOBAL.innodb_undo_log_truncate;
SET GLOBAL innodb_undo_log_truncate = 0;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
-SET @trunc_start=
-(SELECT variable_value FROM information_schema.global_status
-WHERE variable_name = 'innodb_undo_truncations');
create table t1(keyc int primary key, c char(100)) engine = innodb;
create table t2(keyc int primary key, c char(100)) engine = innodb;
-CREATE PROCEDURE populate_t1()
-BEGIN
-DECLARE i INT DEFAULT 1;
-while (i <= 20000) DO
-insert into t1 values (i, 'a');
-SET i = i + 1;
-END WHILE;
-END |
-CREATE PROCEDURE populate_t2()
-BEGIN
-DECLARE i INT DEFAULT 1;
-while (i <= 20000) DO
-insert into t2 values (i, 'a');
-SET i = i + 1;
-END WHILE;
-END |
connect con1,localhost,root,,;
begin;
-call populate_t1();
+insert into t1 select seq,'a' from seq_1_to_20000;
connect con2,localhost,root,,;
begin;
-call populate_t2();
+insert into t2 select seq,'a' from seq_1_to_20000;
connection con1;
update t1 set c = 'mysql';
connection con2;
@@ -49,9 +28,6 @@ connection con2;
commit;
disconnect con2;
connection default;
+set global innodb_fast_shutdown=0;
+# restart
drop table t1, t2;
-drop PROCEDURE populate_t1;
-drop PROCEDURE populate_t2;
-InnoDB 0 transactions not purged
-SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
-SET GLOBAL innodb_undo_log_truncate = @save_truncate;
diff --git a/mysql-test/suite/innodb/t/innodb_defrag_stats.test b/mysql-test/suite/innodb/t/innodb_defrag_stats.test
index 248fd24f0c8..13e4579d3d8 100644
--- a/mysql-test/suite/innodb/t/innodb_defrag_stats.test
+++ b/mysql-test/suite/innodb/t/innodb_defrag_stats.test
@@ -1,28 +1,32 @@
--source include/have_innodb.inc
---source include/have_sequence.inc
---source include/big_test.inc
--source include/not_valgrind.inc
--source include/not_embedded.inc
+--source include/have_sequence.inc
+
+SET GLOBAL innodb_defragment_stats_accuracy = 20;
-select @@global.innodb_stats_persistent;
-set global innodb_defragment_stats_accuracy = 20;
+DELETE FROM mysql.innodb_index_stats;
+
+--echo # Create table.
+CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256),
+ KEY SECOND(a, b)) ENGINE=INNODB STATS_PERSISTENT=0;
-CREATE TABLE t1(a INT PRIMARY KEY, b VARCHAR(256), KEY SECOND(a, b))
-ENGINE=INNODB;
INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_1_to_1024;
--echo # Not enough page splits to trigger persistent stats write yet.
-select * from mysql.innodb_index_stats where table_name='t1'
-and stat_name in ('n_page_split','n_pages_freed,n_leaf_pages_defrag');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_1025_to_2048;
--echo # Persistent stats recorded.
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
-select * from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
--echo # Delete some rows.
+BEGIN;
let $num_delete = 20;
while ($num_delete)
{
@@ -30,58 +34,71 @@ while ($num_delete)
eval delete from t1 where a between $j and $j + 30;
dec $num_delete;
}
+COMMIT;
---source include/restart_mysqld.inc
---echo # Server Restarted
-
---echo # Confirm persistent stats still there after restart.
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
-select * from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
optimize table t1;
-select sleep(2);
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
set global innodb_defragment_stats_accuracy = 40;
-INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_2049_to_4096;
+INSERT INTO t1 (b) SELECT b from t1;
+
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
-INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_4097_to_8192;
+INSERT INTO t1 (b) SELECT b from t1;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't1' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
--echo # Table rename should cause stats rename.
rename table t1 to t2;
-select * from mysql.innodb_index_stats where table_name = 't1';
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_leaf_pages_defrag');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
+select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
+
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_page_split');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed');
+select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_leaf_pages_defrag');
---echo # Drop index should cause stats drop.
+--echo # Drop index should cause stats drop, but will not.
drop index SECOND on t2;
-select * from mysql.innodb_index_stats where table_name = 't2' and index_name = 'SECOND';
+--sorted_result
+SELECT stat_name, stat_value>0 FROM mysql.innodb_index_stats
+WHERE table_name like '%t2%' AND index_name='SECOND';
+
+--echo #
+--echo # MDEV-26636: Statistics must not be written for temporary tables
+--echo #
+SET GLOBAL innodb_defragment_stats_accuracy = 1;
+CREATE TEMPORARY TABLE t (a INT PRIMARY KEY, c CHAR(255) NOT NULL)
+ENGINE=InnoDB;
+INSERT INTO t SELECT seq, '' FROM seq_1_to_100;
--source include/restart_mysqld.inc
---echo Server Restarted
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name = 't2' and stat_name in ('n_leaf_pages_defrag');
+SELECT * FROM mysql.innodb_index_stats where table_name like '%t1%';
+
+--sorted_result
+SELECT table_name, index_name, stat_name, stat_value>0
+FROM mysql.innodb_index_stats;
--echo # Clean up
+# DROP TABLE will not touch persistent statistics if the table has none!
+ALTER TABLE t2 STATS_PERSISTENT=1;
DROP TABLE t2;
-select * from mysql.innodb_index_stats where table_name = 't2';
+SELECT * FROM mysql.innodb_index_stats;
diff --git a/mysql-test/suite/innodb/t/undo_truncate.opt b/mysql-test/suite/innodb/t/undo_truncate.opt
new file mode 100644
index 00000000000..f4d78725c6e
--- /dev/null
+++ b/mysql-test/suite/innodb/t/undo_truncate.opt
@@ -0,0 +1 @@
+--innodb-buffer-pool-size=24M
diff --git a/mysql-test/suite/innodb/t/undo_truncate.test b/mysql-test/suite/innodb/t/undo_truncate.test
index d2a4e287305..9601de482b3 100644
--- a/mysql-test/suite/innodb/t/undo_truncate.test
+++ b/mysql-test/suite/innodb/t/undo_truncate.test
@@ -1,16 +1,16 @@
--source include/have_innodb.inc
--source include/innodb_page_size.inc
--source include/have_undo_tablespaces.inc
+--source include/not_embedded.inc
+--source include/have_sequence.inc
+
+--disable_query_log
+call mtr.add_suppression("InnoDB: Difficult to find free blocks in the buffer pool");
+--enable_query_log
-SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
-SET @save_truncate = @@GLOBAL.innodb_undo_log_truncate;
SET GLOBAL innodb_undo_log_truncate = 0;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
-SET @trunc_start=
-(SELECT variable_value FROM information_schema.global_status
-WHERE variable_name = 'innodb_undo_truncations');
-
#-----------------------------------------------------------------------------
#
# Perform DML action using multiple clients and multiple undo tablespace.
@@ -19,37 +19,14 @@ WHERE variable_name = 'innodb_undo_truncations');
create table t1(keyc int primary key, c char(100)) engine = innodb;
create table t2(keyc int primary key, c char(100)) engine = innodb;
#
-delimiter |;
-CREATE PROCEDURE populate_t1()
-BEGIN
- DECLARE i INT DEFAULT 1;
- while (i <= 20000) DO
- insert into t1 values (i, 'a');
- SET i = i + 1;
- END WHILE;
-END |
-delimiter ;|
-#
-delimiter |;
-CREATE PROCEDURE populate_t2()
-BEGIN
- DECLARE i INT DEFAULT 1;
- while (i <= 20000) DO
- insert into t2 values (i, 'a');
- SET i = i + 1;
- END WHILE;
-END |
-delimiter ;|
-#
-#
let DATADIR = `select @@datadir`;
connect (con1,localhost,root,,);
begin;
-send call populate_t1();
+send insert into t1 select seq,'a' from seq_1_to_20000;
connect (con2,localhost,root,,);
begin;
-send call populate_t2();
+send insert into t2 select seq,'a' from seq_1_to_20000;
connection con1; reap; send update t1 set c = 'mysql';
connection con2; reap; send update t2 set c = 'mysql';
@@ -59,62 +36,25 @@ connection con1; reap; send delete from t1;
connection con2; reap; delete from t2;
connection con1; reap;
-let CHECKFILE = $MYSQL_TMP_DIR/check.txt;
-perl;
-($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size1)
- = stat("$ENV{DATADIR}/undo001");
-($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size2)
- = stat("$ENV{DATADIR}/undo002");
-open(OUT, ">$ENV{CHECKFILE}") || die;
-print OUT "let \$size1='$size1,$size2';\n";
-close(OUT);
-EOF
-
SET GLOBAL innodb_undo_log_truncate = 1;
commit; disconnect con1;
connection con2; commit; disconnect con2;
connection default;
-drop table t1, t2;
-drop PROCEDURE populate_t1;
-drop PROCEDURE populate_t2;
-
---source include/wait_all_purged.inc
-# Truncation will normally not occur with innodb_page_size=64k,
-# and occasionally not with innodb_page_size=32k,
-# because the undo log will not grow enough.
-# TODO: For some reason this does not occur on 4k either!
-if (`select @@innodb_page_size IN (8192,16384)`)
-{
- let $wait_condition = (SELECT variable_value!=@trunc_start
- FROM information_schema.global_status
- WHERE variable_name = 'innodb_undo_truncations');
- source include/wait_condition.inc;
-}
+--replace_regex /.*Trx id counter ([0-9]+).*/\1/
+let $trx_before= `SHOW ENGINE INNODB STATUS`;
+let $trx_before= `select substr('$trx_before',9)+2`;
---source $CHECKFILE
-perl;
-($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size1)
- = stat("$ENV{DATADIR}/undo001");
-($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size2)
- = stat("$ENV{DATADIR}/undo002");
-open(OUT, ">$ENV{CHECKFILE}") || die;
-print OUT "let \$size2='$size1,$size2';\n";
-close(OUT);
-EOF
+set global innodb_fast_shutdown=0;
+--source include/restart_mysqld.inc
+--replace_regex /.*Trx id counter ([0-9]+).*/\1/
+let $trx_after= `SHOW ENGINE INNODB STATUS`;
+let $trx_after= `select substr('$trx_after',9)`;
---source $CHECKFILE
---remove_file $CHECKFILE
+drop table t1, t2;
-if ($size1 == $size2)
+if ($trx_before != $trx_after)
{
- # This fails for innodb_page_size=64k, occasionally also for 32k.
- if (`select @@innodb_page_size IN (8192,16384)`)
- {
- echo Truncation did not happen: $size1;
- }
+ echo Transaction sequence mismatch: $trx_before != $trx_after;
}
-
-SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
-SET GLOBAL innodb_undo_log_truncate = @save_truncate;
diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh
index 562b9b929f2..54632e5f79b 100644
--- a/scripts/wsrep_sst_mariabackup.sh
+++ b/scripts/wsrep_sst_mariabackup.sh
@@ -949,8 +949,10 @@ then
tmpdir=$(parse_cnf "$encgroups" 'tmpdir')
if [ -z "$tmpdir" ]; then
xtmpdir="$(mktemp -d)"
- else
+ elif [ "$OS" = 'Linux' ]; then
xtmpdir=$(mktemp '-d' "--tmpdir=$tmpdir")
+ else
+ xtmpdir=$(TMPDIR="$tmpdir"; mktemp '-d')
fi
wsrep_log_info "Using '$xtmpdir' as mariabackup temporary directory"
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh
index d90e87b68f2..e16ed75cb16 100644
--- a/scripts/wsrep_sst_rsync.sh
+++ b/scripts/wsrep_sst_rsync.sh
@@ -725,8 +725,10 @@ EOF
tmpdir=$(parse_cnf '--mysqld|sst' 'tmpdir')
if [ -z "$tmpdir" ]; then
tmpfile="$(mktemp)"
- else
+ elif [ "$OS" = 'Linux' ]; then
tmpfile=$(mktemp "--tmpdir=$tmpdir")
+ else
+ tmpfile=$(TMPDIR="$tmpdir"; mktemp '-d')
fi
wsrep_log_info "Extracting binlog files:"
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 8b86ec425d4..5a8ea9ea2d2 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -1,5 +1,5 @@
# Copyright (c) 2006, 2014, Oracle and/or its affiliates.
-# Copyright (c) 2010, 2020, MariaDB Corporation.
+# Copyright (c) 2010, 2021, MariaDB Corporation.
#
# 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
@@ -65,6 +65,8 @@ ADD_CUSTOM_COMMAND(
DEPENDS gen_lex_token
)
+FIND_PACKAGE(BISON 2.4)
+
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/yy_mariadb.yy
${CMAKE_CURRENT_BINARY_DIR}/yy_oracle.yy
@@ -72,6 +74,7 @@ ADD_CUSTOM_COMMAND(
"-DOUT1=${CMAKE_CURRENT_BINARY_DIR}/yy_oracle.yy"
"-DOUT2=${CMAKE_CURRENT_BINARY_DIR}/yy_mariadb.yy"
"-DIN=${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy"
+ "-DBISON_VERSION=${BISON_VERSION}"
-P ${CMAKE_CURRENT_SOURCE_DIR}/gen_yy_files.cmake
COMMENT "Building yy_mariadb.yy and yy_oracle.yy from sql_yacc.yy"
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy
@@ -325,9 +328,6 @@ IF(WITH_MYSQLD_LDFLAGS)
ENDIF()
-FIND_PACKAGE(BISON 2.4)
-
-
# Handle out-of-source build from source package with possibly broken
# bison. Copy bison output to from source to build directory, if not already
# there
diff --git a/sql/gen_yy_files.cmake b/sql/gen_yy_files.cmake
index da63c72c37c..3ceb60a95de 100644
--- a/sql/gen_yy_files.cmake
+++ b/sql/gen_yy_files.cmake
@@ -5,6 +5,9 @@ file(READ "${IN}" data)
file(WRITE "${OUT1}" "")
file(WRITE "${OUT2}" "")
set(where 0)
+if(NOT(BISON_VERSION VERSION_LESS "3.0.0"))
+ string(REPLACE "\n%pure-parser" "\n%define api.pure" data "${data}")
+endif()
string(REGEX REPLACE "/\\* sql_yacc\\.yy \\*/" "/* DON'T EDIT THIS FILE. IT'S GENERATED. EDIT sql_yacc.yy INSTEAD */" data "${data}")
while(NOT data STREQUAL "")
string(REGEX MATCH "^(%[ie][^\n]*\n)|((%[^ie\n]|[^%\n])[^\n]*\n)+|\n+" line "${data}")
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index c88bfc4c484..31f5faa72ed 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4928,6 +4928,9 @@ MYSQL_THD create_background_thd()
thd->set_command(COM_DAEMON);
thd->system_thread= SYSTEM_THREAD_GENERIC;
thd->security_ctx->host_or_ip= "";
+ thd->real_id= 0;
+ thd->thread_id= 0;
+ thd->query_id= 0;
return thd;
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 0a2db2ea93a..e35cf17b182 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -631,14 +631,18 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (!table->check_virtual_columns_marked_for_read())
{
DBUG_PRINT("info", ("Trying direct delete"));
- if (select && select->cond &&
- (select->cond->used_tables() == table->map))
+ bool use_direct_delete= !select || !select->cond;
+ if (!use_direct_delete &&
+ (select->cond->used_tables() & ~RAND_TABLE_BIT) == table->map)
{
DBUG_ASSERT(!table->file->pushed_cond);
if (!table->file->cond_push(select->cond))
+ {
+ use_direct_delete= TRUE;
table->file->pushed_cond= select->cond;
+ }
}
- if (!table->file->direct_delete_rows_init())
+ if (use_direct_delete && !table->file->direct_delete_rows_init())
{
/* Direct deleting is supported */
DBUG_PRINT("info", ("Using direct delete"));
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 8daf4b703ba..76b07284a37 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -754,15 +754,20 @@ int mysql_update(THD *thd,
!table->check_virtual_columns_marked_for_write())
{
DBUG_PRINT("info", ("Trying direct update"));
- if (select && select->cond &&
- (select->cond->used_tables() == table->map))
+ bool use_direct_update= !select || !select->cond;
+ if (!use_direct_update &&
+ (select->cond->used_tables() & ~RAND_TABLE_BIT) == table->map)
{
DBUG_ASSERT(!table->file->pushed_cond);
if (!table->file->cond_push(select->cond))
+ {
+ use_direct_update= TRUE;
table->file->pushed_cond= select->cond;
+ }
}
- if (!table->file->info_push(INFO_KIND_UPDATE_FIELDS, &fields) &&
+ if (use_direct_update &&
+ !table->file->info_push(INFO_KIND_UPDATE_FIELDS, &fields) &&
!table->file->info_push(INFO_KIND_UPDATE_VALUES, &values) &&
!table->file->direct_update_rows_init(&fields))
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 87c95616107..b0685871311 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -75,6 +75,9 @@
/* warning C4065: switch statement contains 'default' but no 'case' labels */
#pragma warning (disable : 4065)
#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wunused-label" /* yyexhaustedlab: */
+#endif
int yylex(void *yylval, void *yythd);
diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc
index 9d77577ed42..cc8ec7a5af4 100644
--- a/sql/wsrep_schema.cc
+++ b/sql/wsrep_schema.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2015-2019 Codership Oy <info@codership.com>
+/* Copyright (C) 2015-2021 Codership Oy <info@codership.com>
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
@@ -54,7 +54,7 @@ static const std::string create_cluster_table_str=
"view_seqno BIGINT NOT NULL,"
"protocol_version INT NOT NULL,"
"capabilities INT NOT NULL"
- ") ENGINE=InnoDB";
+ ") ENGINE=InnoDB STATS_PERSISTENT=0";
static const std::string create_members_table_str=
"CREATE TABLE IF NOT EXISTS " + wsrep_schema_str + "." + members_table_str +
@@ -63,7 +63,7 @@ static const std::string create_members_table_str=
"cluster_uuid CHAR(36) NOT NULL,"
"node_name CHAR(32) NOT NULL,"
"node_incoming_address VARCHAR(256) NOT NULL"
- ") ENGINE=InnoDB";
+ ") ENGINE=InnoDB STATS_PERSISTENT=0";
#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
static const std::string cluster_member_history_table_str= "wsrep_cluster_member_history";
@@ -76,7 +76,7 @@ static const std::string create_members_history_table_str=
"last_view_seqno BIGINT NOT NULL,"
"node_name CHAR(32) NOT NULL,"
"node_incoming_address VARCHAR(256) NOT NULL"
- ") ENGINE=InnoDB";
+ ") ENGINE=InnoDB STATS_PERSISTENT=0";
#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
static const std::string create_frag_table_str=
@@ -88,7 +88,7 @@ static const std::string create_frag_table_str=
"flags INT NOT NULL, "
"frag LONGBLOB NOT NULL, "
"PRIMARY KEY (node_uuid, trx_id, seqno)"
- ") ENGINE=InnoDB";
+ ") ENGINE=InnoDB STATS_PERSISTENT=0";
static const std::string delete_from_cluster_table=
"DELETE FROM " + wsrep_schema_str + "." + cluster_table_str;
@@ -96,6 +96,26 @@ static const std::string delete_from_cluster_table=
static const std::string delete_from_members_table=
"DELETE FROM " + wsrep_schema_str + "." + members_table_str;
+/* For rolling upgrade we need to use ALTER. We do not want
+persistent statistics to be collected from these tables. */
+static const std::string alter_cluster_table=
+ "ALTER TABLE " + wsrep_schema_str + "." + cluster_table_str +
+ " STATS_PERSISTENT=0";
+
+static const std::string alter_members_table=
+ "ALTER TABLE " + wsrep_schema_str + "." + members_table_str +
+ " STATS_PERSISTENT=0";
+
+#ifdef WSREP_SCHEMA_MEMBERS_HISTORY
+static const std::string alter_members_history_table=
+ "ALTER TABLE " + wsrep_schema_str + "." + members_history_table_str +
+ " STATS_PERSISTENT=0";
+#endif
+
+static const std::string alter_frag_table=
+ "ALTER TABLE " + wsrep_schema_str + "." + sr_table_str +
+ " STATS_PERSISTENT=0";
+
namespace Wsrep_schema_impl
{
@@ -675,13 +695,27 @@ int Wsrep_schema::init()
Wsrep_schema_impl::execute_SQL(thd,
create_members_history_table_str.c_str(),
create_members_history_table_str.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd,
+ alter_members_history_table.c_str(),
+ alter_members_history_table.size()) ||
#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */
Wsrep_schema_impl::execute_SQL(thd,
create_frag_table_str.c_str(),
- create_frag_table_str.size())) {
+ create_frag_table_str.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd,
+ alter_cluster_table.c_str(),
+ alter_cluster_table.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd,
+ alter_members_table.c_str(),
+ alter_members_table.size()) ||
+ Wsrep_schema_impl::execute_SQL(thd,
+ alter_frag_table.c_str(),
+ alter_frag_table.size()))
+ {
ret= 1;
}
- else {
+ else
+ {
ret= 0;
}
diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc
index 0e21acb4fda..19f6edc7ec7 100644
--- a/storage/innobase/btr/btr0defragment.cc
+++ b/storage/innobase/btr/btr0defragment.cc
@@ -225,6 +225,7 @@ void btr_defragment_save_defrag_stats_if_needed(dict_index_t *index)
{
if (srv_defragment_stats_accuracy != 0 // stats tracking disabled
&& index->table->space_id != 0 // do not track system tables
+ && !index->table->is_temporary()
&& index->stat_defrag_modified_counter
>= srv_defragment_stats_accuracy) {
dict_stats_defrag_pool_add(index);
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 47ca3cdf23b..cd5b3a1843a 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -3387,6 +3387,7 @@ loop:
/* Delete possible entries for the page from the insert buffer:
such can exist if the page belonged to an index which was dropped */
if (page_id < page_id_t{SRV_SPACE_ID_UPPER_BOUND, 0} &&
+ !srv_is_undo_tablespace(page_id.space()) &&
!recv_recovery_is_on())
ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size);
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index fe156c14b2f..ab0b0986010 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -366,10 +366,12 @@ void buf_page_write_complete(const IORequest &request)
const bool temp= fsp_is_system_temporary(bpage->id().space());
mysql_mutex_lock(&buf_pool.mutex);
+ mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
buf_pool.stat.n_pages_written++;
/* While we do not need any mutex for clearing oldest_modification
here, we hope that it will be in the same cache line with io_fix,
whose changes must be protected by buf_pool.mutex. */
+ ut_ad(temp || bpage->oldest_modification() > 2);
bpage->clear_oldest_modification(temp);
ut_ad(bpage->io_fix() == BUF_IO_WRITE);
bpage->set_io_fix(BUF_IO_NONE);
@@ -2234,7 +2236,9 @@ unemployed:
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
- if (!recv_recovery_is_on() && srv_operation == SRV_OPERATION_NORMAL)
+ if (!recv_recovery_is_on() &&
+ !srv_startup_is_before_trx_rollback_phase &&
+ srv_operation == SRV_OPERATION_NORMAL)
log_checkpoint();
mysql_mutex_lock(&buf_pool.flush_list_mutex);
diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc
index 8dd1a8601aa..35ffee7e0d0 100644
--- a/storage/innobase/dict/dict0defrag_bg.cc
+++ b/storage/innobase/dict/dict0defrag_bg.cc
@@ -173,10 +173,10 @@ dict_stats_defrag_pool_del(
/*****************************************************************//**
Get the first index that has been added for updating persistent defrag
stats and eventually save its stats. */
-static void dict_stats_process_entry_from_defrag_pool()
+static void dict_stats_process_entry_from_defrag_pool(THD *thd)
{
- table_id_t table_id;
- index_id_t index_id;
+ table_id_t table_id;
+ index_id_t index_id;
ut_ad(!srv_read_only_mode);
@@ -185,31 +185,28 @@ static void dict_stats_process_entry_from_defrag_pool()
/* no index in defrag pool */
return;
- dict_sys.freeze(SRW_LOCK_CALL);
-
/* If the table is no longer cached, we've already lost the in
memory stats so there's nothing really to write to disk. */
- dict_table_t *table= dict_sys.find_table(table_id);
- dict_index_t *index= table && table->corrupted
- ? nullptr : dict_table_find_index_on_id(table, index_id);
- const bool save= index && !index->is_corrupted();
- if (save)
- table->acquire();
- dict_sys.unfreeze();
- if (save)
+ MDL_ticket *mdl= nullptr;
+ if (dict_table_t *table=
+ dict_table_open_on_id(table_id, false, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED,
+ thd, &mdl))
{
- dict_stats_save_defrag_stats(index);
- table->release();
+ if (dict_index_t *index= !table->corrupted
+ ? dict_table_find_index_on_id(table, index_id) : nullptr)
+ if (!index->is_corrupted())
+ dict_stats_save_defrag_stats(index);
+ dict_table_close(table, false, thd, mdl);
}
}
/**
Get the first index that has been added for updating persistent defrag
stats and eventually save its stats. */
-void dict_defrag_process_entries_from_defrag_pool()
+void dict_defrag_process_entries_from_defrag_pool(THD *thd)
{
while (!defrag_pool.empty())
- dict_stats_process_entry_from_defrag_pool();
+ dict_stats_process_entry_from_defrag_pool(thd);
}
/*********************************************************************//**
diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc
index 91c18c95851..676656122a3 100644
--- a/storage/innobase/dict/dict0stats_bg.cc
+++ b/storage/innobase/dict/dict0stats_bg.cc
@@ -391,7 +391,7 @@ static void dict_stats_func(void*)
THD *thd= innobase_create_background_thd("InnoDB statistics");
set_current_thd(thd);
while (dict_stats_process_entry_from_recalc_pool(thd)) {}
- dict_defrag_process_entries_from_defrag_pool();
+ dict_defrag_process_entries_from_defrag_pool(thd);
set_current_thd(nullptr);
innobase_destroy_background_thd(thd);
}
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 7eb5611bb75..620b5a0e49b 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -564,7 +564,7 @@ void fsp_header_init(fil_space_t* space, uint32_t size, mtr_t* mtr)
in order to avoid optimizing away any unchanged most
significant bytes of FSP_SIZE. */
mtr->write<4,mtr_t::FORCED>(*block, FSP_HEADER_OFFSET + FSP_SIZE
- + block->frame, size);
+ + block->frame, size);
ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ block->frame));
if (auto f = space->flags & ~FSP_FLAGS_MEM_MASK) {
@@ -758,10 +758,12 @@ fsp_try_extend_data_file(fil_space_t *space, buf_block_t *header, mtr_t *mtr)
return(0);
}
- /* We ignore any fragments of a full megabyte when storing the size
- to the space header */
+ /* For the system tablespace, we ignore any fragments of a
+ full megabyte when storing the size to the space header */
- space->size_in_header = ut_2pow_round(space->size, (1024 * 1024) / ps);
+ space->size_in_header = space->id
+ ? space->size
+ : ut_2pow_round(space->size, (1024 * 1024) / ps);
/* recv_sys_t::parse() expects to find a WRITE record that
covers all 4 bytes. Therefore, we must specify mtr_t::FORCED
@@ -1045,11 +1047,36 @@ static
buf_block_t*
fsp_page_create(fil_space_t *space, page_no_t offset, mtr_t *mtr)
{
- buf_block_t *free_block= buf_LRU_get_free_block(false);
- buf_block_t *block= buf_page_create(space, static_cast<uint32_t>(offset),
- space->zip_size(), mtr, free_block);
+ buf_block_t *block, *free_block;
+
+ if (UNIV_UNLIKELY(space->is_being_truncated))
+ {
+ const page_id_t page_id{space->id, offset};
+ const ulint fold= page_id.fold();
+ mysql_mutex_lock(&buf_pool.mutex);
+ block= reinterpret_cast<buf_block_t*>
+ (buf_pool.page_hash_get_low(page_id, fold));
+ if (block && block->page.oldest_modification() <= 1)
+ block= nullptr;
+ mysql_mutex_unlock(&buf_pool.mutex);
+
+ if (block)
+ {
+ ut_ad(block->page.buf_fix_count() >= 1);
+ ut_ad(block->lock.x_lock_count() == 1);
+ ut_ad(mtr->have_x_latch(*block));
+ free_block= block;
+ goto got_free_block;
+ }
+ }
+
+ free_block= buf_LRU_get_free_block(false);
+got_free_block:
+ block= buf_page_create(space, static_cast<uint32_t>(offset),
+ space->zip_size(), mtr, free_block);
if (UNIV_UNLIKELY(block != free_block))
buf_pool.free_block(free_block);
+
fsp_init_file_page(space, block, mtr);
return block;
}
@@ -1753,7 +1780,10 @@ fseg_create(fil_space_t *space, ulint byte_offset, mtr_t *mtr,
goto funct_exit;
}
- ut_ad(block->lock.not_recursive());
+ ut_d(const auto x = block->lock.x_lock_count());
+ ut_ad(x || block->lock.not_recursive());
+ ut_ad(x == 1 || space->is_being_truncated);
+ ut_ad(x <= 2);
ut_ad(!fil_page_get_type(block->frame));
mtr->write<1>(*block, FIL_PAGE_TYPE + 1 + block->frame,
FIL_PAGE_TYPE_SYS);
@@ -2179,14 +2209,14 @@ take_hinted_page:
return(NULL);
}
- if (space->size <= ret_page && !is_system_tablespace(space_id)) {
+ if (space->size <= ret_page && !is_predefined_tablespace(space_id)) {
/* It must be that we are extending a single-table
tablespace whose size is still < 64 pages */
if (ret_page >= FSP_EXTENT_SIZE) {
- ib::error() << "Error (2): trying to extend"
- " a single-table tablespace " << space_id
- << " by single page(s) though the"
+ ib::error() << "Trying to extend '"
+ << space->chain.start->name
+ << "' by single page(s) though the"
<< " space size " << space->size
<< ". Page no " << ret_page << ".";
ut_ad(!has_done_reservation);
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index d7e10405853..a99bada12f9 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -2138,9 +2138,7 @@ inline void buf_page_t::clear_oldest_modification()
it from buf_pool.flush_list */
inline void buf_page_t::clear_oldest_modification(bool temporary)
{
- mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
ut_ad(temporary == fsp_is_system_temporary(id().space()));
- ut_ad(io_fix_ == BUF_IO_WRITE);
if (temporary)
{
ut_ad(oldest_modification() == 2);
diff --git a/storage/innobase/include/dict0defrag_bg.h b/storage/innobase/include/dict0defrag_bg.h
index 0edc6304788..679484ad64e 100644
--- a/storage/innobase/include/dict0defrag_bg.h
+++ b/storage/innobase/include/dict0defrag_bg.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2016, 2020, MariaDB Corporation.
+Copyright (c) 2016, 2021, MariaDB Corporation.
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
@@ -80,12 +80,10 @@ dict_stats_defrag_pool_del(
all entries for the table */
const dict_index_t* index); /*!< in: index to remove */
-/*****************************************************************//**
+/**
Get the first index that has been added for updating persistent defrag
stats and eventually save its stats. */
-void
-dict_defrag_process_entries_from_defrag_pool();
-/*===========================================*/
+void dict_defrag_process_entries_from_defrag_pool(THD *thd);
/*********************************************************************//**
Save defragmentation result.
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index a651a56e8a0..be28528adb0 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -113,12 +113,16 @@ struct completion_callback;
void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key = false,
const completion_callback* cb=nullptr);
-/** write to the log file up to the last log entry.
-@param[in] sync whether we want the written log
-also to be flushed to disk. */
-void
-log_buffer_flush_to_disk(
- bool sync = true);
+/** Write to the log file up to the last log entry.
+@param sync whether to wait for a durable write to complete */
+void log_buffer_flush_to_disk(bool sync= true);
+
+
+/** Prepare to invoke log_write_and_flush(), before acquiring log_sys.mutex. */
+ATTRIBUTE_COLD void log_write_and_flush_prepare();
+
+/** Durably write the log up to log_sys.lsn() and release log_sys.mutex. */
+ATTRIBUTE_COLD void log_write_and_flush();
/** Make a checkpoint */
ATTRIBUTE_COLD void log_make_checkpoint();
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 0085008707e..f72a94d4a39 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -101,6 +101,10 @@ struct mtr_t {
/** Commit the mini-transaction. */
void commit();
+ /** Commit a mini-transaction that is shrinking a tablespace.
+ @param space tablespace that is being shrunk */
+ ATTRIBUTE_COLD void commit_shrink(fil_space_t &space);
+
/** Commit a mini-transaction that did not modify any pages,
but generated some redo log on a higher level, such as
FILE_MODIFY records and an optional FILE_CHECKPOINT marker.
diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic
index 3896f2f6715..f1b2f9aba83 100644
--- a/storage/innobase/include/mtr0mtr.ic
+++ b/storage/innobase/include/mtr0mtr.ic
@@ -48,8 +48,8 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type)
/* If this mtr has x-fixed a clean page then we set
the made_dirty flag. This tells us if we need to
- grab log_flush_order_mutex at mtr_commit so that we
- can insert the dirtied page to the flush list. */
+ grab log_sys.flush_order_mutex at mtr_t::commit() so that we
+ can insert the dirtied page into the flush list. */
if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX)
&& !m_made_dirty) {
diff --git a/storage/innobase/include/sux_lock.h b/storage/innobase/include/sux_lock.h
index c09915cf6de..6d2ddadb9c3 100644
--- a/storage/innobase/include/sux_lock.h
+++ b/storage/innobase/include/sux_lock.h
@@ -98,6 +98,9 @@ public:
ut_ad(recursive);
return recursive == RECURSIVE_X || recursive == RECURSIVE_U;
}
+
+ /** @return the number of X locks being held (by any thread) */
+ unsigned x_lock_count() const { return recursive & RECURSIVE_MAX; }
#endif
/** Acquire a recursive lock */
diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h
index bf1d7b7efab..0cfa5d734be 100644
--- a/storage/innobase/include/trx0rseg.h
+++ b/storage/innobase/include/trx0rseg.h
@@ -43,6 +43,7 @@ trx_rsegf_get(fil_space_t* space, uint32_t page_no, mtr_t* mtr);
/** Create a rollback segment header.
@param[in,out] space system, undo, or temporary tablespace
@param[in] rseg_id rollback segment identifier
+@param[in] max_trx_id new value of TRX_RSEG_MAX_TRX_ID
@param[in,out] sys_header the TRX_SYS page (NULL for temporary rseg)
@param[in,out] mtr mini-transaction
@return the created rollback segment
@@ -51,6 +52,7 @@ buf_block_t*
trx_rseg_header_create(
fil_space_t* space,
ulint rseg_id,
+ trx_id_t max_trx_id,
buf_block_t* sys_header,
mtr_t* mtr);
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 2757571b52c..4d927227944 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -833,15 +833,41 @@ void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key,
DBUG_EXECUTE_IF("crash_after_log_write_upto", DBUG_SUICIDE(););
}
-/** write to the log file up to the last log entry.
-@param[in] sync whether we want the written log
-also to be flushed to disk. */
+/** Write to the log file up to the last log entry.
+@param sync whether to wait for a durable write to complete */
void log_buffer_flush_to_disk(bool sync)
{
ut_ad(!srv_read_only_mode);
log_write_up_to(log_sys.get_lsn(std::memory_order_acquire), sync);
}
+/** Prepare to invoke log_write_and_flush(), before acquiring log_sys.mutex. */
+ATTRIBUTE_COLD void log_write_and_flush_prepare()
+{
+ mysql_mutex_assert_not_owner(&log_sys.mutex);
+
+ while (flush_lock.acquire(log_sys.get_lsn() + 1, nullptr) !=
+ group_commit_lock::ACQUIRED);
+ while (write_lock.acquire(log_sys.get_lsn() + 1, nullptr) !=
+ group_commit_lock::ACQUIRED);
+}
+
+/** Durably write the log and release log_sys.mutex */
+ATTRIBUTE_COLD void log_write_and_flush()
+{
+ ut_ad(!srv_read_only_mode);
+ auto lsn= log_sys.get_lsn();
+ write_lock.set_pending(lsn);
+ log_write(false);
+ ut_a(log_sys.write_lsn == lsn);
+ write_lock.release(lsn);
+
+ lsn= write_lock.value();
+ flush_lock.set_pending(lsn);
+ log_write_flush_to_disk_low(lsn);
+ flush_lock.release(lsn);
+}
+
/********************************************************************
Tries to establish a big enough margin of free space in the log buffer, such
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 3ed547e57bc..3a63749695a 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -461,6 +461,114 @@ void mtr_t::commit()
release_resources();
}
+/** Shrink a tablespace. */
+struct Shrink
+{
+ /** the first non-existing page in the tablespace */
+ const page_id_t high;
+
+ Shrink(const fil_space_t &space) : high({space.id, space.size}) {}
+
+ bool operator()(mtr_memo_slot_t *slot) const
+ {
+ if (!slot->object)
+ return true;
+ switch (slot->type) {
+ default:
+ ut_ad("invalid type" == 0);
+ return false;
+ case MTR_MEMO_SPACE_X_LOCK:
+ ut_ad(high.space() == static_cast<fil_space_t*>(slot->object)->id);
+ return true;
+ case MTR_MEMO_PAGE_X_MODIFY:
+ case MTR_MEMO_PAGE_SX_MODIFY:
+ case MTR_MEMO_PAGE_X_FIX:
+ case MTR_MEMO_PAGE_SX_FIX:
+ auto &bpage= static_cast<buf_block_t*>(slot->object)->page;
+ ut_ad(bpage.io_fix() == BUF_IO_NONE);
+ const auto id= bpage.id();
+ if (id < high)
+ {
+ ut_ad(id.space() == high.space() ||
+ (id == page_id_t{0, TRX_SYS_PAGE_NO} &&
+ srv_is_undo_tablespace(high.space())));
+ break;
+ }
+ ut_ad(id.space() == high.space());
+ ut_ad(bpage.state() == BUF_BLOCK_FILE_PAGE);
+ if (bpage.oldest_modification() > 1)
+ bpage.clear_oldest_modification(false);
+ slot->type= static_cast<mtr_memo_type_t>(slot->type & ~MTR_MEMO_MODIFY);
+ }
+ return true;
+ }
+};
+
+/** Commit a mini-transaction that is shrinking a tablespace.
+@param space tablespace that is being shrunk */
+void mtr_t::commit_shrink(fil_space_t &space)
+{
+ ut_ad(is_active());
+ ut_ad(!is_inside_ibuf());
+ ut_ad(!high_level_read_only);
+ ut_ad(m_modifications);
+ ut_ad(m_made_dirty);
+ ut_ad(!recv_recovery_is_on());
+ ut_ad(m_log_mode == MTR_LOG_ALL);
+ ut_ad(UT_LIST_GET_LEN(space.chain) == 1);
+
+ log_write_and_flush_prepare();
+
+ const lsn_t start_lsn= finish_write(prepare_write()).first;
+
+ mysql_mutex_lock(&log_sys.flush_order_mutex);
+ /* Durably write the reduced FSP_SIZE before truncating the data file. */
+ log_write_and_flush();
+
+ os_file_truncate(space.chain.start->name, space.chain.start->handle,
+ os_offset_t{space.size} << srv_page_size_shift, true);
+
+ if (m_freed_pages)
+ {
+ ut_ad(!m_freed_pages->empty());
+ ut_ad(m_freed_space == &space);
+ ut_ad(memo_contains(*m_freed_space));
+ ut_ad(is_named_space(m_freed_space));
+ m_freed_space->update_last_freed_lsn(m_commit_lsn);
+
+ if (!is_trim_pages())
+ for (const auto &range : *m_freed_pages)
+ m_freed_space->add_free_range(range);
+ else
+ m_freed_space->clear_freed_ranges();
+ delete m_freed_pages;
+ m_freed_pages= nullptr;
+ m_freed_space= nullptr;
+ /* mtr_t::start() will reset m_trim_pages */
+ }
+ else
+ ut_ad(!m_freed_space);
+
+ m_memo.for_each_block_in_reverse(CIterate<Shrink>{space});
+
+ m_memo.for_each_block_in_reverse(CIterate<const ReleaseBlocks>
+ (ReleaseBlocks(start_lsn, m_commit_lsn,
+ m_memo)));
+ mysql_mutex_unlock(&log_sys.flush_order_mutex);
+
+ mysql_mutex_lock(&fil_system.mutex);
+ ut_ad(space.is_being_truncated);
+ ut_ad(space.is_stopping());
+ space.clear_stopping();
+ space.is_being_truncated= false;
+ mysql_mutex_unlock(&fil_system.mutex);
+
+ m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>());
+ srv_stats.log_write_requests.inc();
+
+ release_resources();
+}
+
/** Commit a mini-transaction that did not modify any pages,
but generated some redo log on a higher level, such as
FILE_MODIFY records and an optional FILE_CHECKPOINT marker.
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index 792a9b46e8a..e116c9efc98 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -1637,7 +1637,6 @@ row_fts_merge_insert(
aux_table = dict_table_open_on_name(aux_table_name, false,
DICT_ERR_IGNORE_NONE);
ut_ad(aux_table != NULL);
- aux_table->release();
aux_index = dict_table_get_first_index(aux_table);
ut_ad(!aux_index->is_instant());
@@ -1762,6 +1761,8 @@ row_fts_merge_insert(
}
exit:
+ aux_table->release();
+
fts_sql_commit(trx);
trx->op_info = "";
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index a22d75033c6..15f7796e0da 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1809,7 +1809,9 @@ fewer_threads:
if (history_size &&
trx_purge(n_use_threads,
!(++count % srv_purge_rseg_truncate_frequency) ||
- purge_sys.truncate.current))
+ purge_sys.truncate.current ||
+ (srv_shutdown_state != SRV_SHUTDOWN_NONE &&
+ srv_fast_shutdown == 0)))
continue;
if (m_running == sigcount)
diff --git a/storage/innobase/sync/srw_lock.cc b/storage/innobase/sync/srw_lock.cc
index 4cd4b56bdd0..f3c0afd64e3 100644
--- a/storage/innobase/sync/srw_lock.cc
+++ b/storage/innobase/sync/srw_lock.cc
@@ -223,6 +223,14 @@ template void ssux_lock_impl<false>::destroy();
template void ssux_lock_impl<false>::rd_unlock();
template void ssux_lock_impl<false>::u_unlock();
template void ssux_lock_impl<false>::wr_unlock();
+template void ssux_lock_impl<true>::init();
+template void ssux_lock_impl<true>::destroy();
+template void ssux_lock_impl<true>::read_lock(uint32_t);
+template void ssux_lock_impl<true>::rd_unlock();
+template void ssux_lock_impl<true>::u_unlock();
+template void ssux_lock_impl<true>::wr_unlock();
+template void ssux_lock_impl<true>::write_lock(bool);
+template void ssux_lock_impl<true>::update_lock(uint32_t);
#else /* SUX_LOCK_GENERIC */
static_assert(4 == sizeof(rw_lock), "ABI");
# ifdef _WIN32
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index 866c6db4b7f..b2d602ad5b5 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -546,251 +546,255 @@ function is called, the caller must not have any latches on undo log pages!
*/
static void trx_purge_truncate_history()
{
- ut_ad(purge_sys.head <= purge_sys.tail);
- purge_sys_t::iterator& head = purge_sys.head.trx_no
- ? purge_sys.head : purge_sys.tail;
-
- if (head.trx_no >= purge_sys.low_limit_no()) {
- /* This is sometimes necessary. TODO: find out why. */
- head.trx_no = purge_sys.low_limit_no();
- head.undo_no = 0;
- }
-
- for (auto& rseg : trx_sys.rseg_array) {
- if (rseg.space) {
- trx_purge_truncate_rseg_history(rseg, head);
- }
- }
-
- if (srv_undo_tablespaces_active < 2) {
- return;
- }
-
- while (srv_undo_log_truncate) {
- if (!purge_sys.truncate.current) {
- const ulint threshold = ulint(srv_max_undo_log_size
- >> srv_page_size_shift);
- for (uint32_t i = purge_sys.truncate.last
- ? purge_sys.truncate.last->id
- - srv_undo_space_id_start
- : 0, j = i;; ) {
- uint32_t space_id = srv_undo_space_id_start
- + i;
- ut_ad(srv_is_undo_tablespace(space_id));
- fil_space_t* space= fil_space_get(space_id);
-
- if (space && space->get_size() > threshold) {
- purge_sys.truncate.current = space;
- break;
- }
-
- ++i;
- i %= srv_undo_tablespaces_active;
- if (i == j) {
- break;
- }
- }
- }
-
- if (!purge_sys.truncate.current) {
- return;
- }
-
- fil_space_t& space = *purge_sys.truncate.current;
- /* Undo tablespace always are a single file. */
- ut_a(UT_LIST_GET_LEN(space.chain) == 1);
- fil_node_t* file = UT_LIST_GET_FIRST(space.chain);
- /* The undo tablespace files are never closed. */
- ut_ad(file->is_open());
-
- DBUG_LOG("undo", "marking for truncate: " << file->name);
-
- for (auto& rseg : trx_sys.rseg_array) {
- if (rseg.space == &space) {
- /* Once set, this rseg will
- not be allocated to subsequent
- transactions, but we will wait
- for existing active
- transactions to finish. */
- rseg.set_skip_allocation();
- }
- }
+ ut_ad(purge_sys.head <= purge_sys.tail);
+ purge_sys_t::iterator &head= purge_sys.head.trx_no
+ ? purge_sys.head : purge_sys.tail;
+
+ if (head.trx_no >= purge_sys.low_limit_no())
+ {
+ /* This is sometimes necessary. TODO: find out why. */
+ head.trx_no= purge_sys.low_limit_no();
+ head.undo_no= 0;
+ }
+
+ for (auto &rseg : trx_sys.rseg_array)
+ if (rseg.space)
+ trx_purge_truncate_rseg_history(rseg, head);
+
+ if (srv_undo_tablespaces_active < 2)
+ return;
- for (auto& rseg : trx_sys.rseg_array) {
- if (rseg.space != &space) {
- continue;
- }
- ut_ad(rseg.skip_allocation());
- if (rseg.is_referenced()) {
- return;
- }
- rseg.latch.rd_lock();
- ut_ad(rseg.skip_allocation());
- if (rseg.is_referenced()) {
+ while (srv_undo_log_truncate)
+ {
+ if (!purge_sys.truncate.current)
+ {
+ const ulint threshold=
+ ulint(srv_max_undo_log_size >> srv_page_size_shift);
+ for (uint32_t i= purge_sys.truncate.last
+ ? purge_sys.truncate.last->id - srv_undo_space_id_start : 0,
+ j= i;; )
+ {
+ const uint32_t space_id= srv_undo_space_id_start + i;
+ ut_ad(srv_is_undo_tablespace(space_id));
+ fil_space_t *space= fil_space_get(space_id);
+ ut_a(UT_LIST_GET_LEN(space->chain) == 1);
+
+ if (space && space->get_size() > threshold)
+ {
+ purge_sys.truncate.current= space;
+ break;
+ }
+
+ ++i;
+ i %= srv_undo_tablespaces_active;
+ if (i == j)
+ return;
+ }
+ }
+
+ fil_space_t &space= *purge_sys.truncate.current;
+ /* Undo tablespace always are a single file. */
+ fil_node_t *file= UT_LIST_GET_FIRST(space.chain);
+ /* The undo tablespace files are never closed. */
+ ut_ad(file->is_open());
+
+ DBUG_LOG("undo", "marking for truncate: " << file->name);
+
+ for (auto &rseg : trx_sys.rseg_array)
+ if (rseg.space == &space)
+ /* Once set, this rseg will not be allocated to subsequent
+ transactions, but we will wait for existing active
+ transactions to finish. */
+ rseg.set_skip_allocation();
+
+ for (auto &rseg : trx_sys.rseg_array)
+ {
+ if (rseg.space != &space)
+ continue;
+ rseg.latch.rd_lock();
+ ut_ad(rseg.skip_allocation());
+ if (rseg.is_referenced())
+ {
not_free:
- rseg.latch.rd_unlock();
- return;
- }
-
- if (rseg.curr_size != 1) {
- /* Check if all segments are
- cached and safe to remove. */
- ulint cached = 0;
-
- for (trx_undo_t* undo = UT_LIST_GET_FIRST(
- rseg.undo_cached);
- undo;
- undo = UT_LIST_GET_NEXT(undo_list,
- undo)) {
- if (head.trx_no < undo->trx_id) {
- goto not_free;
- } else {
- cached += undo->size;
- }
- }
-
- ut_ad(rseg.curr_size > cached);
-
- if (rseg.curr_size > cached + 1) {
- goto not_free;
- }
- }
-
- rseg.latch.rd_unlock();
- }
-
- ib::info() << "Truncating " << file->name;
- trx_purge_cleanse_purge_queue(space);
-
- /* Flush all to-be-discarded pages of the tablespace.
-
- During truncation, we do not want any writes to the
- to-be-discarded area, because we must set the space.size
- early in order to have deterministic page allocation.
-
- If a log checkpoint was completed at LSN earlier than our
- mini-transaction commit and the server was killed, then
- discarding the to-be-trimmed pages without flushing would
- break crash recovery. So, we cannot avoid the write. */
- while (buf_flush_list_space(&space));
-
- log_free_check();
-
- /* Re-initialize tablespace, in a single mini-transaction. */
- mtr_t mtr;
- const ulint size = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
- mtr.start();
- mtr.x_lock_space(&space);
-
- /* Adjust the tablespace metadata. */
- mysql_mutex_lock(&fil_system.mutex);
- ut_d(bool stopped=) space.set_stopping();
- ut_ad(!stopped);
- space.is_being_truncated = true;
- if (space.crypt_data) {
- space.reacquire();
- mysql_mutex_unlock(&fil_system.mutex);
- fil_space_crypt_close_tablespace(&space);
- space.release();
- } else {
- mysql_mutex_unlock(&fil_system.mutex);
- }
-
- uint i = 60;
-
- while (space.referenced()) {
- if (!--i) {
- mtr.commit();
- ib::error() << "Failed to freeze"
- " UNDO tablespace "
- << file->name;
- return;
- }
-
- std::this_thread::sleep_for(std::chrono::seconds(1));
- }
-
- /* Associate the undo tablespace with mtr.
- During mtr::commit(), InnoDB can use the undo
- tablespace object to clear all freed ranges */
- mtr.set_named_space(&space);
- mtr.trim_pages(page_id_t(space.id, size));
- fsp_header_init(&space, size, &mtr);
- mysql_mutex_lock(&fil_system.mutex);
- space.size = file->size = size;
- mysql_mutex_unlock(&fil_system.mutex);
-
- buf_block_t* sys_header = trx_sysf_get(&mtr);
-
- for (auto& rseg : trx_sys.rseg_array) {
- if (rseg.space != &space) {
- continue;
- }
-
- buf_block_t* rblock = trx_rseg_header_create(
- purge_sys.truncate.current,
- i, sys_header, &mtr);
- ut_ad(rblock);
- /* These were written by trx_rseg_header_create(). */
- ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
- + rblock->frame));
- ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_HISTORY_SIZE
- + rblock->frame));
- rseg.reinit(rblock
- ? rblock->page.id().page_no() : FIL_NULL);
- }
-
- mtr.commit();
- /* Write-ahead the redo log record. */
- log_write_up_to(mtr.commit_lsn(), true);
-
- /* Trim the file size. */
- os_file_truncate(file->name, file->handle,
- os_offset_t(size) << srv_page_size_shift,
- true);
-
- /* This is only executed by srv_purge_coordinator_thread. */
- export_vars.innodb_undo_truncations++;
-
- /* In MDEV-8319 (10.5) we will PUNCH_HOLE the garbage
- (with write-ahead logging). */
- mysql_mutex_lock(&fil_system.mutex);
- ut_ad(&space == purge_sys.truncate.current);
- ut_ad(space.is_being_truncated);
- purge_sys.truncate.current->clear_stopping();
- purge_sys.truncate.current->is_being_truncated = false;
- mysql_mutex_unlock(&fil_system.mutex);
-
- if (purge_sys.rseg != NULL
- && purge_sys.rseg->last_page_no == FIL_NULL) {
- /* If purge_sys.rseg is pointing to rseg that
- was recently truncated then move to next rseg
- element. Note: Ideally purge_sys.rseg should
- be NULL because purge should complete
- processing of all the records but there is
- purge_batch_size that can force the purge loop
- to exit before all the records are purged and
- in this case purge_sys.rseg could point to a
- valid rseg waiting for next purge cycle. */
- purge_sys.next_stored = false;
- purge_sys.rseg = NULL;
- }
-
- DBUG_EXECUTE_IF("ib_undo_trunc",
- ib::info() << "ib_undo_trunc";
- log_buffer_flush_to_disk();
- DBUG_SUICIDE(););
-
- for (auto& rseg : trx_sys.rseg_array) {
- if (rseg.space == &space) {
- rseg.clear_skip_allocation();
- }
- }
-
- ib::info() << "Truncated " << file->name;
- purge_sys.truncate.last = purge_sys.truncate.current;
- purge_sys.truncate.current = NULL;
- }
+ rseg.latch.rd_unlock();
+ return;
+ }
+
+ if (rseg.curr_size != 1)
+ {
+ /* Check if all segments are cached and safe to remove. */
+ ulint cached= 0;
+ for (trx_undo_t *undo= UT_LIST_GET_FIRST(rseg.undo_cached); undo;
+ undo= UT_LIST_GET_NEXT(undo_list, undo))
+ {
+ if (head.trx_no < undo->trx_id)
+ goto not_free;
+ else
+ cached+= undo->size;
+ }
+
+ ut_ad(rseg.curr_size > cached);
+
+ if (rseg.curr_size > cached + 1)
+ goto not_free;
+ }
+
+ rseg.latch.rd_unlock();
+ }
+
+ ib::info() << "Truncating " << file->name;
+ trx_purge_cleanse_purge_queue(space);
+
+ log_free_check();
+
+ mtr_t mtr;
+ mtr.start();
+ mtr.x_lock_space(&space);
+
+ /* Lock all modified pages of the tablespace.
+
+ During truncation, we do not want any writes to the file.
+
+ If a log checkpoint was completed at LSN earlier than our
+ mini-transaction commit and the server was killed, then
+ discarding the to-be-trimmed pages without flushing would
+ break crash recovery. */
+ mysql_mutex_lock(&buf_pool.flush_list_mutex);
+
+ for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; )
+ {
+ ut_ad(bpage->oldest_modification());
+ ut_ad(bpage->in_file());
+
+ buf_page_t *prev= UT_LIST_GET_PREV(list, bpage);
+
+ if (bpage->id().space() == space.id &&
+ bpage->oldest_modification() != 1)
+ {
+ ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE);
+ auto block= reinterpret_cast<buf_block_t*>(bpage);
+ block->fix();
+ buf_pool.flush_hp.set(prev);
+ mysql_mutex_unlock(&buf_pool.flush_list_mutex);
+
+#ifdef BTR_CUR_HASH_ADAPT
+ ut_ad(!block->index); /* There is no AHI on undo tablespaces. */
+#endif
+ block->lock.x_lock();
+ mysql_mutex_lock(&buf_pool.flush_list_mutex);
+ ut_ad(bpage->io_fix() == BUF_IO_NONE);
+
+ if (bpage->oldest_modification() > 1)
+ {
+ bpage->clear_oldest_modification(false);
+ mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
+ }
+ else
+ {
+ block->lock.x_unlock();
+ block->unfix();
+ }
+
+ if (prev != buf_pool.flush_hp.get())
+ {
+ /* Rescan, because we may have lost the position. */
+ bpage= UT_LIST_GET_LAST(buf_pool.flush_list);
+ continue;
+ }
+ }
+
+ bpage= prev;
+ }
+
+ mysql_mutex_unlock(&buf_pool.flush_list_mutex);
+
+ /* Re-initialize tablespace, in a single mini-transaction. */
+ const ulint size= SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
+
+ /* Adjust the tablespace metadata. */
+ mysql_mutex_lock(&fil_system.mutex);
+ space.set_stopping();
+ space.is_being_truncated= true;
+ if (space.crypt_data)
+ {
+ space.reacquire();
+ mysql_mutex_unlock(&fil_system.mutex);
+ fil_space_crypt_close_tablespace(&space);
+ space.release();
+ }
+ else
+ mysql_mutex_unlock(&fil_system.mutex);
+
+ for (auto i= 6000; space.referenced();
+ std::this_thread::sleep_for(std::chrono::milliseconds(10)))
+ {
+ if (!--i)
+ {
+ mtr.commit();
+ ib::error() << "Failed to freeze UNDO tablespace " << file->name;
+ return;
+ }
+ }
+
+ /* Associate the undo tablespace with mtr.
+ During mtr::commit_shrink(), InnoDB can use the undo
+ tablespace object to clear all freed ranges */
+ mtr.set_named_space(&space);
+ mtr.trim_pages(page_id_t(space.id, size));
+ fsp_header_init(&space, size, &mtr);
+ mysql_mutex_lock(&fil_system.mutex);
+ space.size= file->size= size;
+ mysql_mutex_unlock(&fil_system.mutex);
+
+ buf_block_t *sys_header= trx_sysf_get(&mtr);
+
+ for (auto &rseg : trx_sys.rseg_array)
+ {
+ if (rseg.space != &space)
+ continue;
+
+ buf_block_t *rblock= trx_rseg_header_create(&space,
+ &rseg - trx_sys.rseg_array,
+ trx_sys.get_max_trx_id(),
+ sys_header, &mtr);
+ ut_ad(rblock);
+ /* These were written by trx_rseg_header_create(). */
+ ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT + rblock->frame));
+ ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_HISTORY_SIZE +
+ rblock->frame));
+ rseg.reinit(rblock ? rblock->page.id().page_no() : FIL_NULL);
+ }
+
+ mtr.commit_shrink(space);
+
+ /* No mutex; this is only updated by the purge coordinator. */
+ export_vars.innodb_undo_truncations++;
+
+ if (purge_sys.rseg && purge_sys.rseg->last_page_no == FIL_NULL)
+ {
+ /* If purge_sys.rseg is pointing to rseg that was recently
+ truncated then move to next rseg element.
+
+ Note: Ideally purge_sys.rseg should be NULL because purge should
+ complete processing of all the records but srv_purge_batch_size
+ can force the purge loop to exit before all the records are purged. */
+ purge_sys.rseg= nullptr;
+ purge_sys.next_stored= false;
+ }
+
+ DBUG_EXECUTE_IF("ib_undo_trunc", ib::info() << "ib_undo_trunc";
+ log_buffer_flush_to_disk();
+ DBUG_SUICIDE(););
+
+ for (auto &rseg : trx_sys.rseg_array)
+ if (rseg.space == &space)
+ rseg.clear_skip_allocation();
+
+ ib::info() << "Truncated " << file->name;
+ purge_sys.truncate.last= purge_sys.truncate.current;
+ ut_ad(&space == purge_sys.truncate.current);
+ purge_sys.truncate.current= nullptr;
+ }
}
/***********************************************************************//**
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 50ffbe0a138..3e392e1df48 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -316,6 +316,7 @@ void trx_rseg_format_upgrade(buf_block_t *rseg_header, mtr_t *mtr)
/** Create a rollback segment header.
@param[in,out] space system, undo, or temporary tablespace
@param[in] rseg_id rollback segment identifier
+@param[in] max_trx_id new value of TRX_RSEG_MAX_TRX_ID
@param[in,out] sys_header the TRX_SYS page (NULL for temporary rseg)
@param[in,out] mtr mini-transaction
@return the created rollback segment
@@ -324,6 +325,7 @@ buf_block_t*
trx_rseg_header_create(
fil_space_t* space,
ulint rseg_id,
+ trx_id_t max_trx_id,
buf_block_t* sys_header,
mtr_t* mtr)
{
@@ -344,10 +346,16 @@ trx_rseg_header_create(
+ block->frame));
ut_ad(0 == mach_read_from_4(TRX_RSEG_HISTORY_SIZE + TRX_RSEG
+ block->frame));
+ ut_ad(0 == mach_read_from_4(TRX_RSEG_MAX_TRX_ID + TRX_RSEG
+ + block->frame));
/* Initialize the history list */
flst_init(block, TRX_RSEG_HISTORY + TRX_RSEG, mtr);
+ mtr->write<8,mtr_t::MAYBE_NOP>(*block,
+ TRX_RSEG + TRX_RSEG_MAX_TRX_ID
+ + block->frame, max_trx_id);
+
/* Reset the undo log slots */
mtr->memset(block, TRX_RSEG_UNDO_SLOTS + TRX_RSEG,
TRX_RSEG_N_SLOTS * 4, 0xff);
@@ -695,7 +703,7 @@ void trx_temp_rseg_create()
mtr.x_lock_space(fil_system.temp_space);
buf_block_t* rblock = trx_rseg_header_create(
- fil_system.temp_space, i, NULL, &mtr);
+ fil_system.temp_space, i, 0, NULL, &mtr);
trx_sys.temp_rsegs[i].init(fil_system.temp_space,
rblock->page.id().page_no());
mtr.commit();
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 10991ce3f39..65ac991bb68 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -191,7 +191,7 @@ trx_sysf_create(
/* Create the first rollback segment in the SYSTEM tablespace */
slot_no = trx_sys_rseg_find_free(block);
buf_block_t* rblock = trx_rseg_header_create(fil_system.sys_space,
- slot_no, block, mtr);
+ slot_no, 0, block, mtr);
ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID);
ut_a(rblock->page.id() == page_id_t(0, FSP_FIRST_RSEG_PAGE_NO));
@@ -293,7 +293,7 @@ static trx_rseg_t *trx_rseg_create(uint32_t space_id)
{
ulint rseg_id= trx_sys_rseg_find_free(sys_header);
if (buf_block_t *rblock= rseg_id == ULINT_UNDEFINED
- ? nullptr : trx_rseg_header_create(space, rseg_id, sys_header,
+ ? nullptr : trx_rseg_header_create(space, rseg_id, 0, sys_header,
&mtr))
{
ut_ad(trx_sysf_rseg_get_space(sys_header, rseg_id) == space_id);
diff --git a/storage/spider/mysql-test/spider/r/udf_pushdown.result b/storage/spider/mysql-test/spider/r/udf_pushdown.result
new file mode 100644
index 00000000000..4ca734165e7
--- /dev/null
+++ b/storage/spider/mysql-test/spider/r/udf_pushdown.result
@@ -0,0 +1,218 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+child3_1
+child3_2
+child3_3
+#
+# MDEV-26545 Spider does not correctly handle UDF and stored function in where conds
+#
+
+##### enable general_log #####
+connection child2_1;
+SET @general_log_backup = @@global.general_log;
+SET @log_output_backup = @@global.log_output;
+SET @@global.general_log = 1;
+SET @@global.log_output = "TABLE";
+TRUNCATE TABLE mysql.general_log;
+
+##### create databases #####
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+##### create tables #####
+connection child2_1;
+CHILD_CREATE_TABLE
+connection master_1;
+MASTER_CREATE_TABLE
+CREATE TABLE ta_l (
+id INT NOT NULL,
+a INT,
+PRIMARY KEY(id)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO ta_l VALUES
+(1, 11),
+(2, 22),
+(3, 33),
+(4, 44),
+(5, 55);
+
+##### create functions #####
+connection master_1;
+CREATE FUNCTION `plusone`( param INT ) RETURNS INT
+BEGIN
+RETURN param + 1;
+END //
+connection child2_1;
+CREATE FUNCTION `plusone`( param INT ) RETURNS INT
+BEGIN
+RETURN param + 1;
+END //
+
+########## spider_use_pushdown_udf=0 ##########
+connection master_1;
+SET @@spider_use_pushdown_udf = 0;
+
+##### test SELECTs #####
+connection master_1;
+SELECT * FROM ta_l WHERE id = plusone(1);
+id a
+2 22
+SELECT * FROM ta_l WHERE id IN (plusone(1), plusone(2)) AND a = plusone(32);
+id a
+3 33
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE "%select%" AND argument NOT LIKE "%argument%";
+argument
+select `id`,`a` from `auto_test_remote`.`ta_r`
+select `id`,`a` from `auto_test_remote`.`ta_r`
+
+##### test UPDATEs #####
+connection master_1;
+UPDATE ta_l SET a = plusone(221) WHERE id = plusone(1);
+SELECT * FROM ta_l;
+id a
+1 11
+2 222
+3 33
+4 44
+5 55
+UPDATE ta_l SET a = plusone(332) WHERE id IN (plusone(1), plusone(2)) AND a = plusone(32);
+SELECT * FROM ta_l;
+id a
+1 11
+2 222
+3 333
+4 44
+5 55
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE "%update%" AND argument NOT LIKE "%argument%";
+argument
+select `id`,`a` from `auto_test_remote`.`ta_r` for update
+update `auto_test_remote`.`ta_r` set `a` = 222 where `id` = 2 limit 1
+select `id`,`a` from `auto_test_remote`.`ta_r` for update
+update `auto_test_remote`.`ta_r` set `a` = 333 where `id` = 3 and `a` = 33 limit 1
+
+##### test DELETEs #####
+connection master_1;
+DELETE FROM ta_l WHERE id = plusone(1);
+SELECT * FROM ta_l;
+id a
+1 11
+3 333
+4 44
+5 55
+DELETE FROM ta_l WHERE id IN (plusone(1), plusone(2), plusone(3)) AND a = plusone(43);
+SELECT * FROM ta_l;
+id a
+1 11
+3 333
+5 55
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE (argument LIKE "%delete%" OR argument LIKE "%update%") AND argument NOT LIKE "%argument%";
+argument
+select `id` from `auto_test_remote`.`ta_r` for update
+delete from `auto_test_remote`.`ta_r` where `id` = 2 limit 1
+select `id`,`a` from `auto_test_remote`.`ta_r` for update
+delete from `auto_test_remote`.`ta_r` where `id` = 4 and `a` = 44 limit 1
+
+##### reset records #####
+connection master_1;
+TRUNCATE TABLE ta_l;
+INSERT INTO ta_l VALUES
+(1, 11),
+(2, 22),
+(3, 33),
+(4, 44),
+(5, 55);
+
+########## spider_use_pushdown_udf=1 ##########
+connection master_1;
+SET @@spider_use_pushdown_udf = 1;
+
+##### test SELECTs #####
+connection master_1;
+SELECT * FROM ta_l WHERE id = plusone(1);
+id a
+2 22
+SELECT * FROM ta_l WHERE id IN (plusone(1), plusone(2)) AND a = plusone(32);
+id a
+3 33
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE "%select%" AND argument NOT LIKE "%argument%";
+argument
+select t0.`id` `id`,t0.`a` `a` from `auto_test_remote`.`ta_r` t0 where (t0.`id` = (`plusone`(1)))
+select t0.`id` `id`,t0.`a` `a` from `auto_test_remote`.`ta_r` t0 where ((t0.`id` in( (`plusone`(1)) , (`plusone`(2)))) and (t0.`a` = (`plusone`(32))))
+
+##### test UPDATEs #####
+connection master_1;
+UPDATE ta_l SET a = plusone(221) WHERE id = plusone(1);
+SELECT * FROM ta_l;
+id a
+1 11
+2 222
+3 33
+4 44
+5 55
+UPDATE ta_l SET a = plusone(332) WHERE id IN (plusone(1), plusone(2)) AND a = plusone(32);
+SELECT * FROM ta_l;
+id a
+1 11
+2 222
+3 333
+4 44
+5 55
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE "%update%" AND argument NOT LIKE "%argument%";
+argument
+update `auto_test_remote`.`ta_r` set `a` = (`plusone`(221)) where (`id` = (`plusone`(1)))
+update `auto_test_remote`.`ta_r` set `a` = (`plusone`(332)) where ((`id` in( (`plusone`(1)) , (`plusone`(2)))) and (`a` = (`plusone`(32))))
+
+##### test DELETEs #####
+connection master_1;
+DELETE FROM ta_l WHERE id = plusone(1);
+SELECT * FROM ta_l;
+id a
+1 11
+3 333
+4 44
+5 55
+DELETE FROM ta_l WHERE id IN (plusone(1), plusone(2), plusone(3)) AND a = plusone(43);
+SELECT * FROM ta_l;
+id a
+1 11
+3 333
+5 55
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE (argument LIKE "%delete%" OR argument LIKE "%update%") AND argument NOT LIKE "%argument%";
+argument
+delete from `auto_test_remote`.`ta_r` where (`id` = (`plusone`(1)))
+delete from `auto_test_remote`.`ta_r` where ((`id` in( (`plusone`(1)) , (`plusone`(2)) , (`plusone`(3)))) and (`a` = (`plusone`(43))))
+
+deinit
+connection master_1;
+DROP FUNCTION `plusone`;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+SET @@global.general_log = @general_log_backup;
+SET @@global.log_output = @log_output_backup;
+DROP FUNCTION `plusone`;
+DROP DATABASE IF EXISTS auto_test_remote;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+child3_1
+child3_2
+child3_3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/t/udf_pushdown.inc b/storage/spider/mysql-test/spider/t/udf_pushdown.inc
new file mode 100644
index 00000000000..160e8af21b2
--- /dev/null
+++ b/storage/spider/mysql-test/spider/t/udf_pushdown.inc
@@ -0,0 +1,48 @@
+--echo
+--echo ##### test SELECTs #####
+--connection master_1
+SELECT * FROM ta_l WHERE id = plusone(1);
+SELECT * FROM ta_l WHERE id IN (plusone(1), plusone(2)) AND a = plusone(32);
+
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ SELECT argument FROM mysql.general_log WHERE argument LIKE "%select%" AND argument NOT LIKE "%argument%";
+ --disable_query_log
+ TRUNCATE TABLE mysql.general_log;
+ --enable_query_log
+}
+
+--echo
+--echo ##### test UPDATEs #####
+--connection master_1
+UPDATE ta_l SET a = plusone(221) WHERE id = plusone(1);
+SELECT * FROM ta_l;
+UPDATE ta_l SET a = plusone(332) WHERE id IN (plusone(1), plusone(2)) AND a = plusone(32);
+SELECT * FROM ta_l;
+
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ SELECT argument FROM mysql.general_log WHERE argument LIKE "%update%" AND argument NOT LIKE "%argument%";
+ --disable_query_log
+ TRUNCATE TABLE mysql.general_log;
+ --enable_query_log
+}
+
+--echo
+--echo ##### test DELETEs #####
+--connection master_1
+DELETE FROM ta_l WHERE id = plusone(1);
+SELECT * FROM ta_l;
+DELETE FROM ta_l WHERE id IN (plusone(1), plusone(2), plusone(3)) AND a = plusone(43);
+SELECT * FROM ta_l;
+
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ SELECT argument FROM mysql.general_log WHERE (argument LIKE "%delete%" OR argument LIKE "%update%") AND argument NOT LIKE "%argument%";
+ --disable_query_log
+ TRUNCATE TABLE mysql.general_log;
+ --enable_query_log
+}
diff --git a/storage/spider/mysql-test/spider/t/udf_pushdown.test b/storage/spider/mysql-test/spider/t/udf_pushdown.test
new file mode 100644
index 00000000000..2eadbbbb40b
--- /dev/null
+++ b/storage/spider/mysql-test/spider/t/udf_pushdown.test
@@ -0,0 +1,141 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source test_init.inc
+--enable_result_log
+--enable_query_log
+
+--echo #
+--echo # MDEV-26545 Spider does not correctly handle UDF and stored function in where conds
+--echo #
+
+let $CHILD_CREATE_TABLE=
+ CREATE TABLE ta_r (
+ id INT NOT NULL,
+ a INT,
+ PRIMARY KEY(id)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+
+let $MASTER_CREATE_TABLE_OUTPUT=
+ CREATE TABLE ta_l (
+ id INT NOT NULL,
+ a INT,
+ PRIMARY KEY(id)
+ ) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+
+let $MASTER_CREATE_TABLE=
+ CREATE TABLE ta_l (
+ id INT NOT NULL,
+ a INT,
+ PRIMARY KEY(id)
+ ) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+
+--echo
+--echo ##### enable general_log #####
+--connection child2_1
+SET @general_log_backup = @@global.general_log;
+SET @log_output_backup = @@global.log_output;
+SET @@global.general_log = 1;
+SET @@global.log_output = "TABLE";
+TRUNCATE TABLE mysql.general_log;
+
+--echo
+--echo ##### create databases #####
+--connection master_1
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ CREATE DATABASE auto_test_remote;
+ USE auto_test_remote;
+}
+
+--echo
+--echo ##### create tables #####
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ --disable_query_log
+ echo CHILD_CREATE_TABLE;
+ eval $CHILD_CREATE_TABLE;
+ --enable_query_log
+}
+
+--connection master_1
+--disable_query_log
+echo MASTER_CREATE_TABLE;
+echo $MASTER_CREATE_TABLE_OUTPUT;
+eval $MASTER_CREATE_TABLE;
+--enable_query_log
+
+INSERT INTO ta_l VALUES
+ (1, 11),
+ (2, 22),
+ (3, 33),
+ (4, 44),
+ (5, 55);
+
+--echo
+--echo ##### create functions #####
+--connection master_1
+DELIMITER //;
+CREATE FUNCTION `plusone`( param INT ) RETURNS INT
+BEGIN
+ RETURN param + 1;
+END //
+DELIMITER ;//
+
+--connection child2_1
+DELIMITER //;
+CREATE FUNCTION `plusone`( param INT ) RETURNS INT
+BEGIN
+ RETURN param + 1;
+END //
+DELIMITER ;//
+
+--echo
+--echo ########## spider_use_pushdown_udf=0 ##########
+--connection master_1
+SET @@spider_use_pushdown_udf = 0;
+--source udf_pushdown.inc
+
+--echo
+--echo ##### reset records #####
+--connection master_1
+TRUNCATE TABLE ta_l;
+INSERT INTO ta_l VALUES
+ (1, 11),
+ (2, 22),
+ (3, 33),
+ (4, 44),
+ (5, 55);
+
+--echo
+--echo ########## spider_use_pushdown_udf=1 ##########
+--connection master_1
+SET @@spider_use_pushdown_udf = 1;
+--source udf_pushdown.inc
+
+--echo
+--echo deinit
+--disable_warnings
+--connection master_1
+DROP FUNCTION `plusone`;
+DROP DATABASE IF EXISTS auto_test_local;
+if ($USE_CHILD_GROUP2)
+{
+ --connection child2_1
+ SET @@global.general_log = @general_log_backup;
+ SET @@global.log_output = @log_output_backup;
+ DROP FUNCTION `plusone`;
+ DROP DATABASE IF EXISTS auto_test_remote;
+}
+--disable_query_log
+--disable_result_log
+--source test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--echo
+--echo end of test
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index 10b4fb7cee4..62e6e2f1245 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -6676,11 +6676,17 @@ int spider_db_mbase_util::open_item_func(
separator_str_length = SPIDER_SQL_AND_LEN;
}
break;
+ case Item_func::FUNC_SP:
case Item_func::UDF_FUNC:
use_pushdown_udf = spider_param_use_pushdown_udf(
spider->wide_handler->trx->thd,
spider->share->use_pushdown_udf);
if (!use_pushdown_udf)
+ /*
+ This is the default behavior because the remote nodes may deal with
+ the function in an unexpected way (e.g. not having the same
+ definition). Users can turn it on if they know what they are doing.
+ */
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
if (str)
{
diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc
index ec0949b579f..b23877ca92a 100644
--- a/storage/spider/spd_param.cc
+++ b/storage/spider/spd_param.cc
@@ -2005,7 +2005,7 @@ static MYSQL_THDVAR_INT(
"Remote server transmission existence when UDF is used at condition and \"engine_condition_pushdown=1\"", /* comment */
NULL, /* check */
NULL, /* update */
- -1, /* def */
+ 0, /* def */
-1, /* min */
1, /* max */
0 /* blk */
diff --git a/wsrep-lib b/wsrep-lib
-Subproject 4f1c201c9d8ba96f9f43e9aafe8bb6a6c8aeceb
+Subproject efb4aab090cb9c1b57b9e7f9988ae1c41f48344