1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge 10.6 into 10.7

This commit is contained in:
Marko Mäkelä
2021-09-24 15:32:39 +03:00
64 changed files with 1336 additions and 958 deletions

View File

@@ -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 @@ Youre 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 theyd 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.

View File

@@ -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 theyd like, and a live developer will be available to assist.

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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');
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
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.
# 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';
database_name table_name index_name last_update stat_name stat_value sample_size stat_description
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
Server Restarted
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
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
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
1
# Clean up
DROP TABLE t2;
select * from mysql.innodb_index_stats where table_name = 't2';
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;
database_name table_name index_name last_update stat_name stat_value sample_size stat_description

View File

@@ -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;

View File

@@ -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
select @@global.innodb_stats_persistent;
set global innodb_defragment_stats_accuracy = 20;
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 = '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');
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');
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 (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');
--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');
--echo # Drop index should cause stats drop.
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, 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;

View File

@@ -0,0 +1 @@
--innodb-buffer-pool-size=24M

View File

@@ -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;
--replace_regex /.*Trx id counter ([0-9]+).*/\1/
let $trx_before= `SHOW ENGINE INNODB STATUS`;
let $trx_before= `select substr('$trx_before',9)+2`;
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)`;
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)`)
if ($trx_before != $trx_after)
{
let $wait_condition = (SELECT variable_value!=@trunc_start
FROM information_schema.global_status
WHERE variable_name = 'innodb_undo_truncations');
source include/wait_condition.inc;
echo Transaction sequence mismatch: $trx_before != $trx_after;
}
--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
--source $CHECKFILE
--remove_file $CHECKFILE
if ($size1 == $size2)
{
# 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;
}
}
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
SET GLOBAL innodb_undo_log_truncate = @save_truncate;

View File

@@ -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"

View File

@@ -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:"

View File

@@ -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

View File

@@ -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}")

View File

@@ -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;
}

View File

@@ -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"));

View File

@@ -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))
{

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
/*********************************************************************//**

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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.

View File

@@ -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();

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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

View File

@@ -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.

View File

@@ -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 = "";

View File

@@ -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)

View File

@@ -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

View File

@@ -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;
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;
}
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);
}
}
for (auto &rseg : trx_sys.rseg_array)
if (rseg.space)
trx_purge_truncate_rseg_history(rseg, head);
if (srv_undo_tablespaces_active < 2) {
return;
}
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);
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;
}
if (space && space->get_size() > threshold)
{
purge_sys.truncate.current= space;
break;
}
++i;
i %= srv_undo_tablespaces_active;
if (i == j) {
break;
}
}
}
++i;
i %= srv_undo_tablespaces_active;
if (i == j)
return;
}
}
if (!purge_sys.truncate.current) {
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());
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);
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) {
/* 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;
}
ut_ad(rseg.skip_allocation());
if (rseg.is_referenced()) {
return;
}
rseg.latch.rd_lock();
ut_ad(rseg.skip_allocation());
if (rseg.is_referenced()) {
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;
}
rseg.latch.rd_unlock();
return;
}
if (rseg.curr_size != 1) {
/* Check if all segments are
cached and safe to remove. */
ulint cached = 0;
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;
}
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);
ut_ad(rseg.curr_size > cached);
if (rseg.curr_size > cached + 1)
goto not_free;
}
if (rseg.curr_size > cached + 1) {
goto not_free;
}
}
rseg.latch.rd_unlock();
}
rseg.latch.rd_unlock();
}
ib::info() << "Truncating " << file->name;
trx_purge_cleanse_purge_queue(space);
ib::info() << "Truncating " << file->name;
trx_purge_cleanse_purge_queue(space);
log_free_check();
/* Flush all to-be-discarded pages of the tablespace.
mtr_t mtr;
mtr.start();
mtr.x_lock_space(&space);
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.
/* Lock all modified pages of the tablespace.
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));
During truncation, we do not want any writes to the file.
log_free_check();
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);
/* 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);
for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; )
{
ut_ad(bpage->oldest_modification());
ut_ad(bpage->in_file());
/* 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);
}
buf_page_t *prev= UT_LIST_GET_PREV(list, bpage);
uint i = 60;
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);
while (space.referenced()) {
if (!--i) {
mtr.commit();
ib::error() << "Failed to freeze"
" UNDO tablespace "
<< file->name;
return;
}
#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);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
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();
}
/* 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);
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;
}
}
buf_block_t* sys_header = trx_sysf_get(&mtr);
bpage= prev;
}
for (auto& rseg : trx_sys.rseg_array) {
if (rseg.space != &space) {
continue;
}
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
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);
}
/* Re-initialize tablespace, in a single mini-transaction. */
const ulint size= SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
mtr.commit();
/* Write-ahead the redo log record. */
log_write_up_to(mtr.commit_lsn(), true);
/* 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);
/* Trim the file size. */
os_file_truncate(file->name, file->handle,
os_offset_t(size) << srv_page_size_shift,
true);
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;
}
}
/* This is only executed by srv_purge_coordinator_thread. */
export_vars.innodb_undo_truncations++;
/* 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);
/* 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);
buf_block_t *sys_header= trx_sysf_get(&mtr);
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;
}
for (auto &rseg : trx_sys.rseg_array)
{
if (rseg.space != &space)
continue;
DBUG_EXECUTE_IF("ib_undo_trunc",
ib::info() << "ib_undo_trunc";
log_buffer_flush_to_disk();
DBUG_SUICIDE(););
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);
}
for (auto& rseg : trx_sys.rseg_array) {
if (rseg.space == &space) {
rseg.clear_skip_allocation();
}
}
mtr.commit_shrink(space);
ib::info() << "Truncated " << file->name;
purge_sys.truncate.last = purge_sys.truncate.current;
purge_sys.truncate.current = NULL;
}
/* 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;
}
}
/***********************************************************************//**

View File

@@ -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();

View File

@@ -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);

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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 */