1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

Merge 10.6 into 10.11

This commit is contained in:
Marko Mäkelä
2024-02-08 15:04:46 +02:00
87 changed files with 3227 additions and 689 deletions

View File

@@ -1273,8 +1273,9 @@ static int get_options(int *argc, char ***argv)
if (opt_slave_data)
{
opt_lock_all_tables= !opt_single_transaction;
opt_master_data= 0;
opt_delete_master_logs= 0;
if (opt_slave_data != MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL)
opt_master_data= 0;
}
/* Ensure consistency of the set of binlog & locking options */
@@ -1287,10 +1288,7 @@ static int get_options(int *argc, char ***argv)
return(EX_USAGE);
}
if (opt_master_data)
{
opt_lock_all_tables= !opt_single_transaction;
opt_slave_data= 0;
}
if (opt_single_transaction || opt_lock_all_tables)
lock_tables= 0;
if (enclosed && opt_enclosed)
@@ -6227,17 +6225,12 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos,
}
/* SHOW MASTER STATUS reports file and position */
print_comment(md_result_file, 0,
"\n--\n-- Position to start replication or point-in-time "
"recovery from\n--\n\n");
fprintf(md_result_file,
"%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
(use_gtid ? "-- " : comment_prefix), file, offset);
/* gtid */
if (have_mariadb_gtid)
{
print_comment(md_result_file, 0,
"\n--\n-- GTID to start replication from\n--\n\n");
"\n-- Preferably use GTID to start replication from GTID "
"position:\n\n");
if (use_gtid)
fprintf(md_result_file,
"%sCHANGE MASTER TO MASTER_USE_GTID=slave_pos;\n",
@@ -6246,6 +6239,19 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos,
"%sSET GLOBAL gtid_slave_pos='%s';\n",
(!use_gtid ? "-- " : comment_prefix), gtid_pos);
}
/* SHOW MASTER STATUS reports file and position */
print_comment(md_result_file, 0,
"\n--\n-- Alternately, following is the position of the binary "
"logging from SHOW MASTER STATUS at point of backup."
"\n-- Use this when creating a replica of the primary server "
"where the backup was made."
"\n-- The new server will be connecting to the primary server "
"where the backup was taken."
"\n--\n\n");
fprintf(md_result_file,
"%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
(use_gtid ? "-- " : comment_prefix), file, offset);
check_io(md_result_file);
if (!consistent_binlog_pos)
@@ -6324,7 +6330,6 @@ static int do_show_slave_status(MYSQL *mysql_con, int use_gtid,
(opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
const char *gtid_comment_prefix= (use_gtid ? comment_prefix : "-- ");
const char *nogtid_comment_prefix= (!use_gtid ? comment_prefix : "-- ");
int set_gtid_done= 0;
if (mysql_query_with_error_report(mysql_con, &slave,
multi_source ?
@@ -6340,23 +6345,36 @@ static int do_show_slave_status(MYSQL *mysql_con, int use_gtid,
return 1;
}
print_comment(md_result_file, 0,
"\n--\n-- The following is the SQL position of the replication "
"taken from SHOW SLAVE STATUS at the time of backup.\n"
"-- Use this position when creating a clone of, or replacement "
"server, from where the backup was taken."
"\n-- This new server will connects to the same primary "
"server%s.\n--\n",
multi_source ? "(s)" : "");
if (multi_source)
{
char gtid_pos[MAX_GTID_LENGTH];
if (have_mariadb_gtid && get_gtid_pos(gtid_pos, 0))
{
mysql_free_result(slave);
return 1;
}
print_comment(md_result_file, 0,
"-- GTID position to start replication:\n");
fprintf(md_result_file, "%sSET GLOBAL gtid_slave_pos='%s';\n",
gtid_comment_prefix, gtid_pos);
}
if (use_gtid)
print_comment(md_result_file, 0,
"\n-- Use only the MASTER_USE_GTID=slave_pos or "
"MASTER_LOG_FILE/MASTER_LOG_POS in the statements below."
"\n\n");
while ((row= mysql_fetch_row(slave)))
{
if (multi_source && !set_gtid_done)
{
char gtid_pos[MAX_GTID_LENGTH];
if (have_mariadb_gtid && get_gtid_pos(gtid_pos, 0))
{
mysql_free_result(slave);
return 1;
}
if (opt_comments)
fprintf(md_result_file, "\n--\n-- Gtid position to start replication "
"from\n--\n\n");
fprintf(md_result_file, "%sSET GLOBAL gtid_slave_pos='%s';\n",
gtid_comment_prefix, gtid_pos);
set_gtid_done= 1;
}
if (row[9 + multi_source] && row[21 + multi_source])
{
if (use_gtid)
@@ -6370,11 +6388,6 @@ static int do_show_slave_status(MYSQL *mysql_con, int use_gtid,
}
/* SHOW MASTER STATUS reports file and position */
if (opt_comments)
fprintf(md_result_file,
"\n--\n-- Position to start replication or point-in-time "
"recovery from (the master of this slave)\n--\n\n");
if (multi_source)
fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO ",
nogtid_comment_prefix, row[0]);
@@ -6395,6 +6408,7 @@ static int do_show_slave_status(MYSQL *mysql_con, int use_gtid,
check_io(md_result_file);
}
}
fprintf(md_result_file, "\n");
mysql_free_result(slave);
return 0;
}

View File

@@ -4,6 +4,9 @@ SET(WITH_PCRE "auto" CACHE STRING
"Which pcre to use (possible values are 'bundled', 'system', or 'auto')")
MACRO(BUNDLE_PCRE2)
SET(WITH_PCRE "bundled" CACHE STRING
"Which pcre to use (possible values are 'bundled', 'system', or 'auto')")
SET(dir "${CMAKE_BINARY_DIR}/extra/pcre2")
SET(PCRE_INCLUDE_DIRS ${dir}/src/pcre2-build ${dir}/src/pcre2/src)
MESSAGE(STATUS "Will download and bundle pcre2")

View File

@@ -88,7 +88,7 @@ sanity_checks() {
# If datadir location is not changed int configuration
# then it's not printed with /usr/sbin/mariadbd --print-defaults
# then we use 'sane' default.
if [ -z "$datadir"]
if [ -z "$datadir" ]
then
datadir="/var/lib/mysql"
fi

1
debian/rules vendored
View File

@@ -98,7 +98,6 @@ endif
-DCOMPILATION_COMMENT="mariadb.org binary distribution" \
-DMYSQL_SERVER_SUFFIX="-$(DEB_VERSION_REVISION)" \
-DSYSTEM_TYPE="debian-$(DEB_HOST_GNU_SYSTEM)" \
-DCMAKE_SYSTEM_PROCESSOR=$(DEB_HOST_ARCH) \
-DBUILD_CONFIG=mysql_release \
-DCONC_DEFAULT_CHARSET=utf8mb4 \
-DPLUGIN_AWS_KEY_MANAGEMENT=NO \

View File

@@ -47,6 +47,12 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
#include <stdlib.h>
#include <string.h>
#include <limits>
#ifdef HAVE_PWD_H
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <pwd.h>
#endif
#include "common.h"
#include "xtrabackup.h"
#include "srv0srv.h"
@@ -92,11 +98,54 @@ MYSQL *mysql_connection;
extern my_bool opt_ssl_verify_server_cert, opt_use_ssl;
/*
get_os_user()
Ressemles read_user_name() from libmariadb/libmariadb/mariadb_lib.c.
*/
#if !defined(_WIN32)
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
struct passwd *getpwuid(uid_t);
char* getlogin(void);
#endif
static const char *get_os_user() // Posix
{
if (!geteuid())
return "root";
#ifdef HAVE_GETPWUID
struct passwd *pw;
const char *str;
if ((pw= getpwuid(geteuid())) != NULL)
return pw->pw_name;
if ((str= getlogin()) != NULL)
return str;
#endif
if ((str= getenv("USER")) ||
(str= getenv("LOGNAME")) ||
(str= getenv("LOGIN")))
return str;
return NULL;
}
#else
static const char *get_os_user() // Windows
{
return getenv("USERNAME");
}
#endif // _WIN32
MYSQL *
xb_mysql_connect()
{
MYSQL *connection = mysql_init(NULL);
char mysql_port_str[std::numeric_limits<int>::digits10 + 3];
const char *user= opt_user ? opt_user : get_os_user();
sprintf(mysql_port_str, "%d", opt_port);
@@ -126,7 +175,7 @@ xb_mysql_connect()
msg("Connecting to MariaDB server host: %s, user: %s, password: %s, "
"port: %s, socket: %s", opt_host ? opt_host : "localhost",
opt_user ? opt_user : "not set",
user ? user : "not set",
opt_password ? "set" : "not set",
opt_port != 0 ? mysql_port_str : "not set",
opt_socket ? opt_socket : "not set");
@@ -147,7 +196,7 @@ xb_mysql_connect()
if (!mysql_real_connect(connection,
opt_host ? opt_host : "localhost",
opt_user,
user,
opt_password,
"" /*database*/, opt_port,
opt_socket, 0)) {

View File

@@ -0,0 +1,44 @@
/* Copyright (c) 2019, 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 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 St, Fifth Floor, Boston, MA 02110-1335 USA */
#pragma once
/**
@file include/mysql/service_print_check_msg.h
This service provides functions to write messages for check or repair
*/
#ifdef __cplusplus
extern "C" {
#endif
extern struct print_check_msg_service_st {
void (*print_check_msg)(MYSQL_THD, const char *db_name, const char *table_name,
const char *op, const char *msg_type, const char *message,
my_bool print_to_log);
} *print_check_msg_service;
#ifdef MYSQL_DYNAMIC_PLUGIN
# define print_check_msg_context(_THD) print_check_msg_service->print_check_msg
#else
extern void print_check_msg(MYSQL_THD, const char *db_name, const char *table_name,
const char *op, const char *msg_type, const char *message,
my_bool print_to_log);
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -44,6 +44,7 @@
#define VERSION_wsrep 0x0500
#define VERSION_json 0x0100
#define VERSION_thd_mdl 0x0100
#define VERSION_print_check_msg 0x0100
#define VERSION_sql_service 0x0101
#define VERSION_provider_bzip2 0x0100

View File

@@ -25,6 +25,7 @@ SET(MYSQLSERVICES_SOURCES
my_crypt_service.c
my_md5_service.c
my_print_error_service.c
print_check_msg_service.c
my_sha1_service.c
my_sha2_service.c
my_snprintf_service.c

View File

@@ -0,0 +1,18 @@
/* Copyright (c) 2024, MariaDB Plc
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <service_versions.h>
SERVICE_VERSION print_check_msg_context= (void*) VERSION_print_check_msg;

View File

@@ -0,0 +1,297 @@
if ($cnf == "galera2_to_mariadb")
{
--let MASTER_MYPORT= $NODE_MYPORT_1
--connect master, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connect slave, 127.0.0.1, root, , test, $NODE_MYPORT_3
--disable_query_log
--replace_result $MASTER_MYPORT ###
--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$MASTER_MYPORT, MASTER_USE_GTID=NO;
--enable_query_log
START SLAVE;
--source include/wait_for_slave_to_start.inc
--let XTRABACKUP_BACKUP_OPTIONS=--no-defaults --user=root --host='127.0.0.1' --port=$NODE_MYPORT_3
--let XTRABACKUP_COPY_BACK_OPTIONS= --no-defaults
}
if ($cnf == "mariadb_to_mariadb")
{
--let XTRABACKUP_BACKUP_OPTIONS=--defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2
--let XTRABACKUP_COPY_BACK_OPTIONS=--defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2
}
--connection master
--let $MYSQLD_DATADIR_MASTER= `select @@datadir`
--connection slave
--let $MYSQLD_DATADIR_SLAVE= `select @@datadir`
# This test covers the filename:pos based synchronization
# between the master and the slave.
# If we ever need to test a GTID based synchronization,
# it should be done in a separate test.
--echo ##############################################################
--echo ### Initial block with some transactions
--echo ### Slave: Make sure replication is not using GTID
--connection slave
--let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1)
--echo # Using_Gtid=$value
--echo ### Master: Create and populate t1
--connection master
CREATE TABLE t1(a TEXT) ENGINE=InnoDB;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#00:stmt#00 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#00:stmt#01 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#00:stmt#02 - slave run#0, before backup');
COMMIT;
--sync_slave_with_master
--echo ##############################################################
--echo ### Run the last transaction before mariadb-backup --backup
--echo ### Remember SHOW MASTER STATUS and @@gtid_binlog_pos
--echo ### before and after the transaction.
--echo ### Master: Rember MASTER STATUS and @@gtid_binlog_pos before tr#01
--connection master
--let $master_before_tr01_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1)
--let $master_before_tr01_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1)
--let $master_before_tr01_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos`
--echo ### Slave: Remember MASTER STATUS and @@gtid_binlog_pos before tr#01
--connection slave
--let $slave_before_tr01_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1)
--let $slave_before_tr01_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1)
--let $slave_before_tr01_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos`
--echo ### Master: Run the actual last transaction before the backup
--connection master
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#01:stmt#00 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#01:stmt#01 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#01:stmt#02 - slave run#0, before backup');
COMMIT;
--sync_slave_with_master
--echo ### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01
--connection master
--let $master_after_tr01_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1)
--let $master_after_tr01_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1)
--let $master_after_tr01_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos`
--echo ### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01
--connection slave
--let $slave_after_tr01_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1)
--let $slave_after_tr01_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1)
--let $slave_after_tr01_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos`
--echo ##############################################################
--echo ### Running `mariadb-backup --backup,--prepare` and checking
--echo ### that xtrabackup_slave_info and xtrabackup_binlog_info are OK
--echo ### Slave: Create a backup
--let $backup_slave=$MYSQLTEST_VARDIR/tmp/backup-slave
--disable_result_log
--exec $XTRABACKUP $XTRABACKUP_BACKUP_OPTIONS --slave-info --backup --target-dir=$backup_slave
--enable_result_log
--echo ### Slave: Prepare the backup
--exec $XTRABACKUP --prepare --target-dir=$backup_slave
--echo ### Slave: xtrabackup files:
--echo ############################ xtrabackup_slave_info
--replace_result $master_after_tr01_show_master_status_file master_after_tr01_show_master_status_file $master_after_tr01_show_master_status_position master_after_tr01_show_master_status_position
--cat_file $backup_slave/xtrabackup_slave_info
--echo ############################ xtrabackup_binlog_info
--replace_result $slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_file $slave_after_tr01_show_master_status_position slave_after_tr01_show_master_status_position $slave_after_tr01_gtid_binlog_pos slave_after_tr01_gtid_binlog_pos
--cat_file $backup_slave/xtrabackup_binlog_info
--echo ############################
--echo ##############################################################
--echo ### Run more transactions after the backup:
--echo ### - while the slave is still running, then
--echo ### - while the slave is shut down
--echo ### Master: Run another transaction while the slave is still running
--connection master
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup');
INSERT INTO t1 VALUES ('tr#02:stmt#01 - slave run#0, after backup');
INSERT INTO t1 VALUES ('tr#02:stmt@02 - slave run#0, after backup');
COMMIT;
--sync_slave_with_master
--echo ### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02
--connection master
--let $master_after_tr02_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1)
--let $master_after_tr02_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1)
--let $master_after_tr02_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos`
--echo ### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02
--connection slave
--let $slave_after_tr02_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1)
--let $slave_after_tr02_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1)
--let $slave_after_tr02_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos`
--echo ### Master: Checking SHOW BINLOG EVENTS
--connection master
--vertical_results
### The BEGIN event
--replace_column 4 # 5 #
--replace_result $master_after_tr01_show_master_status_file master_after_tr01_show_master_status_file $master_after_tr01_show_master_status_position master_after_tr01_show_master_status_position $master_after_tr02_gtid_binlog_pos master_after_tr02_gtid_binlog_pos
--eval SHOW BINLOG EVENTS IN '$master_after_tr01_show_master_status_file' FROM $master_after_tr01_show_master_status_position LIMIT 0,1
### The INSERT event
--replace_column 2 # 4 # 5 #
--replace_result $master_after_tr01_show_master_status_file master_after_tr01_show_master_status_file $master_after_tr01_show_master_status_position master_after_tr01_show_master_status_position
# Hide the difference between row and stmt binary logging
--replace_regex /use `test`; // /(Query|Annotate_rows)/Query_or_Annotate_rows/
--eval SHOW BINLOG EVENTS IN '$master_after_tr01_show_master_status_file' FROM $master_after_tr01_show_master_status_position LIMIT 1,1
--horizontal_results
--echo ### Slave: Checking SHOW BINLOG EVENTS
--connection slave
--vertical_results
### The BEGIN event
--replace_column 2 # 5 #
--replace_result $slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_file $slave_after_tr01_show_master_status_position slave_after_tr01_show_master_status_position $slave_after_tr02_gtid_binlog_pos slave_after_tr02_gtid_binlog_pos
--eval SHOW BINLOG EVENTS IN '$slave_after_tr01_show_master_status_file' FROM $slave_after_tr01_show_master_status_position LIMIT 0,1
### The INSERT event
--replace_column 2 # 4 # 5 #
--replace_result $slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_file $slave_after_tr01_show_master_status_position slave_after_tr01_show_master_status_position $slave_after_tr02_gtid_binlog_pos slave_after_tr02_gtid_binlog_pos
# Hide the difference between row and stmt binary logging
--replace_regex /use `test`; // /(Query|Annotate_rows)/Query_or_Annotate_rows/
--eval SHOW BINLOG EVENTS IN '$slave_after_tr01_show_master_status_file' FROM $slave_after_tr01_show_master_status_position LIMIT 1,1
--horizontal_results
--echo ### Slave: Stop replication
--connection slave
STOP SLAVE;
--source include/wait_for_slave_to_stop.inc
RESET SLAVE;
--echo ### Slave: Shutdown the server
if ($cnf == "mariadb_to_mariadb")
{
--let $rpl_server_number= 2
--source include/rpl_stop_server.inc
}
if ($cnf == "galera2_to_mariadb")
{
--connection slave
--source $MYSQL_TEST_DIR/include/shutdown_mysqld.inc
}
--echo ### Master: Run a transaction while the slave is shut down
--connection master
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#03:stmt#00 - after slave run#0, slave is shut down, after backup');
INSERT INTO t1 VALUES ('tr#03:stmt#01 - after slave run#0, slave is shut down, after backup');
INSERT INTO t1 VALUES ('tr#03:stmt#02 - after slave run#0, slave is shut down, after backup');
COMMIT;
--echo ##############################################################
--echo ### Emulate starting a new virgin slave
--echo ### Slave: Remove the data directory
--rmdir $MYSQLD_DATADIR_SLAVE
--echo ### Slave: Copy back the backup
--exec $XTRABACKUP $XTRABACKUP_COPY_BACK_OPTIONS --copy-back --datadir=$MYSQLD_DATADIR_SLAVE --target-dir=$backup_slave
--echo ### Slave: Restart the server
if ($cnf == "mariadb_to_mariadb")
{
--let $rpl_server_number= 2
--source include/rpl_start_server.inc
--source include/wait_until_connected_again.inc
}
if ($cnf == "galera2_to_mariadb")
{
--connection slave
--source $MYSQL_TEST_DIR/include/start_mysqld.inc
}
--echo ### Slave: Display the restored data before START SLAVE
--connection slave
SELECT * FROM t1 ORDER BY a;
--echo ### Slave: Execute the CHANGE MASTER statement to set up the host and port
--replace_result $MASTER_MYPORT ###
--eval CHANGE MASTER '' TO MASTER_USER='root', MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_CONNECT_RETRY=1
--echo ### Slave: Execute the CHANGE MASTER statement from xtrabackup_slave_info
--replace_result $master_after_tr01_show_master_status_file master_after_tr01_show_master_status_file $master_after_tr01_show_master_status_position master_after_tr01_show_master_status_position
--source $backup_slave/xtrabackup_slave_info
--echo ### Slave: Execute START SLAVE
--source include/start_slave.inc
--echo ### Master: Wait for the slave to apply all master events
--connection master
--sync_slave_with_master slave
--echo ### Slave: Make sure replication is not using GTID after the slave restart
--connection slave
--let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1)
--echo # Using_Gtid=$value
--echo ### Slave: Display the restored data after START SLAVE
--connection slave
SELECT * FROM t1 ORDER BY a;
--echo ##############################################################
--echo ### Continue master transactions, check the new slave replicates well.
--echo ### Master: Run a transaction after restarting replication
--connection master
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#04:stmt#00 - slave run#1');
INSERT INTO t1 VALUES ('tr#04:stmt#01 - slave run#1');
INSERT INTO t1 VALUES ('tr#04:stmt#02 - slave run#1');
COMMIT;
--sync_slave_with_master
--echo ### Slave: Display the restored data + new transactions
--connection slave
SELECT * FROM t1 ORDER BY a;
--echo ##############################################################
--echo ### Cleanup
--echo ### Removing the backup directory
--rmdir $backup_slave
--connection master
DROP TABLE t1;
--sync_slave_with_master
if ($cnf == "mariadb_to_mariadb")
{
--source include/rpl_end.inc
}
if ($cnf == "galera2_to_mariadb")
{
STOP SLAVE;
--source include/wait_for_slave_to_stop.inc
RESET SLAVE ALL;
--connection master
set global wsrep_on=OFF;
RESET MASTER;
set global wsrep_on=ON;
}

View File

@@ -87,12 +87,16 @@ sub flush_out {
$out_line = "";
}
use if $^O eq "MSWin32", "threads::shared";
my $flush_lock :shared;
# Print to stdout
sub print_out {
if(IS_WIN32PERL) {
$out_line .= $_[0];
# Flush buffered output on new lines.
if (rindex($_[0], "\n") != -1) {
lock($flush_lock);
flush_out();
}
} else {

View File

@@ -5,6 +5,8 @@
--source include/innodb_prefix_index_cluster_optimization.inc
--source include/no_valgrind_without_big.inc
--source include/innodb_stable_estimates.inc
SET SESSION DEFAULT_STORAGE_ENGINE='InnoDB';
set @innodb_stats_persistent_save= @@innodb_stats_persistent;

View File

@@ -9,23 +9,27 @@ use test;
connection slave;
-- SET GLOBAL gtid_slave_pos='';
CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
STOP ALL SLAVES;
-- SET GLOBAL gtid_slave_pos='';
CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
START ALL SLAVES;
STOP ALL SLAVES;
-- SET GLOBAL gtid_slave_pos='';
CHANGE MASTER '' TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_MYPORT, MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
START ALL SLAVES;
start slave;
Warnings:
Note 1254 Slave is already running
-- SET GLOBAL gtid_slave_pos='';
CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
start slave;
Warnings:
Note 1254 Slave is already running
*** Test mysqldump --dump-slave GTID functionality.
*** Test mysqldump --dump-slave GTID/non-gtid functionality.
connection master;
SET gtid_seq_no = 1000;
CREATE TABLE t1 (a INT PRIMARY KEY);
@@ -35,36 +39,170 @@ connection slave;
CREATE TABLE t2 (a INT PRIMARY KEY);
DROP TABLE t2;
1. --dump-slave=1
1. --dump-slave=1 --gtid
SET GLOBAL gtid_slave_pos='0-1-1001';
CHANGE MASTER '' TO MASTER_USE_GTID=slave_pos;
-- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
2. --dump-slave=2
1a. --dump-slave=1
-- SET GLOBAL gtid_slave_pos='0-1-1001';
CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
2. --dump-slave=2 --gtid
-- SET GLOBAL gtid_slave_pos='0-1-1001';
-- CHANGE MASTER '' TO MASTER_USE_GTID=slave_pos;
-- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
*** Test mysqldump --master-data GTID functionality.
1. --master-data=1
-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
2. --dump-slave=2
-- SET GLOBAL gtid_slave_pos='0-1-1001';
-- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
*** Test mysqldump --master-data GTID/non-gtid functionality.
1. --master-data=1 --gtid
CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
SET GLOBAL gtid_slave_pos='0-2-1003';
2. --master-data=2
-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
1a. --master-data=1
-- SET GLOBAL gtid_slave_pos='0-2-1003';
CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
2. --master-data=2 --gtid
-- CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
-- SET GLOBAL gtid_slave_pos='0-2-1003';
-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
2a. --master-data=2
-- SET GLOBAL gtid_slave_pos='0-2-1003';
-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
3. --master-data --single-transaction --gtid
CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
SET GLOBAL gtid_slave_pos='0-2-1003';
-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
3a. --master-data --single-transaction
-- SET GLOBAL gtid_slave_pos='0-2-1003';
CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
4. --master-data=2 --dump-slave=2 --single-transaction --gtid (MDEV-4827)
-- MariaDB dump--
-- Host: localhost Database: test
-- ------------------------------------------------------
-- Server version
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-- Preferably use GTID to start replication from GTID position:
-- CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
-- SET GLOBAL gtid_slave_pos='0-2-1003';
3. --master-data --single-transaction
--
-- Alternately, following is the position of the binary logging from SHOW MASTER STATUS at point of backup.
-- Use this when creating a replica of the primary server where the backup was made.
-- The new server will be connecting to the primary server where the backup was taken.
--
-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
SET GLOBAL gtid_slave_pos='0-2-1003';
--
-- The following is the SQL position of the replication taken from SHOW SLAVE STATUS at the time of backup.
-- Use this position when creating a clone of, or replacement server, from where the backup was taken.
-- This new server will connects to the same primary server(s).
--
-- GTID position to start replication:
-- SET GLOBAL gtid_slave_pos='0-1-1001';
-- Use only the MASTER_USE_GTID=slave_pos or MASTER_LOG_FILE/MASTER_LOG_POS in the statements below.
-- CHANGE MASTER '' TO MASTER_USE_GTID=slave_pos;
-- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed
4a. --master-data=2 --dump-slave=2 --single-transaction (MDEV-4827)
-- MariaDB dump--
-- Host: localhost Database: test
-- ------------------------------------------------------
-- Server version
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-- Preferably use GTID to start replication from GTID position:
-- SET GLOBAL gtid_slave_pos='0-2-1003';
--
-- Alternately, following is the position of the binary logging from SHOW MASTER STATUS at point of backup.
-- Use this when creating a replica of the primary server where the backup was made.
-- The new server will be connecting to the primary server where the backup was taken.
--
-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START;
--
-- The following is the SQL position of the replication taken from SHOW SLAVE STATUS at the time of backup.
-- Use this position when creating a clone of, or replacement server, from where the backup was taken.
-- This new server will connects to the same primary server(s).
--
-- GTID position to start replication:
-- SET GLOBAL gtid_slave_pos='0-1-1001';
-- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed
connection master;
CREATE TABLE t (
id int
@@ -77,8 +215,8 @@ include/stop_slave.inc
change master to master_use_gtid=slave_pos;
connection master;
# Ensuring the binlog dump thread is killed on primary...
-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000002', MASTER_LOG_POS=BINLOG_START;
-- SET GLOBAL gtid_slave_pos='0-1-1005';
-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000002', MASTER_LOG_POS=BINLOG_START;
connection slave;
include/start_slave.inc
include/rpl_end.inc

View File

@@ -37,7 +37,7 @@ start slave;
start slave;
--echo *** Test mysqldump --dump-slave GTID functionality.
--echo *** Test mysqldump --dump-slave GTID/non-gtid functionality.
--connection master
SET gtid_seq_no = 1000;
@@ -52,37 +52,80 @@ CREATE TABLE t2 (a INT PRIMARY KEY);
DROP TABLE t2;
--echo
--echo 1. --dump-slave=1
--echo 1. --dump-slave=1 --gtid
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --dump-slave=1 --gtid test
--echo
--echo 2. --dump-slave=2
--echo 1a. --dump-slave=1
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --dump-slave=1 test
--echo
--echo 2. --dump-slave=2 --gtid
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --dump-slave=2 --gtid test
--echo *** Test mysqldump --master-data GTID functionality.
--echo
--echo 1. --master-data=1
--echo 2. --dump-slave=2
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --dump-slave=2 test
--echo *** Test mysqldump --master-data GTID/non-gtid functionality.
--echo
--echo 1. --master-data=1 --gtid
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --master-data=1 --gtid test
--echo
--echo 2. --master-data=2
--echo 1a. --master-data=1
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --master-data=1 test
--echo
--echo 2. --master-data=2 --gtid
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --master-data=2 --gtid test
--echo
--echo 3. --master-data --single-transaction
--echo 2a. --master-data=2
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --master-data=2 test
--echo
--echo 3. --master-data --single-transaction --gtid
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --master-data --single-transaction --gtid test
--echo
--echo 3a. --master-data --single-transaction
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/
--exec $MYSQL_DUMP_SLAVE --compact --master-data --single-transaction test
--echo
--echo 4. --master-data=2 --dump-slave=2 --single-transaction --gtid (MDEV-4827)
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ /MariaDB dump.*/MariaDB dump/ /Dump completed.*/Dump completed/ /Server version.*/Server version/
--exec $MYSQL_DUMP_SLAVE --master-data=2 --dump-slave=2 --single-transaction --gtid test
--echo
--echo
--echo 4a. --master-data=2 --dump-slave=2 --single-transaction (MDEV-4827)
--echo
--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ /MariaDB dump.*/MariaDB dump/ /Dump completed.*/Dump completed/ /Server version.*/Server version/
--exec $MYSQL_DUMP_SLAVE --master-data=2 --dump-slave=2 --single-transaction test
--echo
#
# MDEV-32611 Added test for mysqldump --delete-master-logs option.
# This options is alias of

View File

@@ -88,15 +88,142 @@ sel
]
set optimizer_trace=@tmp;
drop table t0,t1,t10;
set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
set histogram_size=@save_histogram_size;
set use_stat_tables= @save_use_stat_tables;
#
# End of 10.4 tests
#
#
# MDEV-33314: Crash inside calculate_cond_selectivity_for_table() with many columns
#
set optimizer_use_condition_selectivity= 4;
set use_stat_tables= preferably;
#
# create table t1 (col0 int, col1 int, col2 int, ...);
#
$create_tbl;
#
# insert into t1 select seq, ... seq from seq_1_to_10;
#
$insert_cmd;
analyze table t1 persistent for all;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
set @trace_tmp=@@optimizer_trace;
set optimizer_trace=1;
#
# Basic testcase: don't crash for many-column selectivity
# explain extended select * from t1 where col0>1 and col1>1 and col2>1 and ...
#
$query_tbl;
EXPLAIN
{
"query_block": {
"select_id": 1,
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 100,
"filtered": 53.32928848,
"attached_condition": "t1.col0 > 1 and t1.col1 > 1 and t1.col2 > 1 and t1.col3 > 1 and t1.col4 > 1 and t1.col5 > 1 and t1.col6 > 1 and t1.col7 > 1 and t1.col8 > 1 and t1.col9 > 1 and t1.col10 > 1 and t1.col11 > 1 and t1.col12 > 1 and t1.col13 > 1 and t1.col14 > 1 and t1.col15 > 1 and t1.col16 > 1 and t1.col17 > 1 and t1.col18 > 1 and t1.col19 > 1 and t1.col20 > 1 and t1.col21 > 1 and t1.col22 > 1 and t1.col23 > 1 and t1.col24 > 1 and t1.col25 > 1 and t1.col26 > 1 and t1.col27 > 1 and t1.col28 > 1 and t1.col29 > 1 and t1.col30 > 1 and t1.col31 > 1 and t1.col32 > 1 and t1.col33 > 1 and t1.col34 > 1 and t1.col35 > 1 and t1.col36 > 1 and t1.col37 > 1 and t1.col38 > 1 and t1.col39 > 1 and t1.col40 > 1 and t1.col41 > 1 and t1.col42 > 1 and t1.col43 > 1 and t1.col44 > 1 and t1.col45 > 1 and t1.col46 > 1 and t1.col47 > 1 and t1.col48 > 1 and t1.col49 > 1 and t1.col50 > 1 and t1.col51 > 1 and t1.col52 > 1 and t1.col53 > 1 and t1.col54 > 1 and t1.col55 > 1 and t1.col56 > 1 and t1.col57 > 1 and t1.col58 > 1 and t1.col59 > 1 and t1.col60 > 1 and t1.col61 > 1 and t1.col62 > 1 and t1.col63 > 1 and t1.col64 > 1 and t1.col65 > 1 and t1.col66 > 1 and t1.col67 > 1 and t1.col68 > 1 and t1.col69 > 1 and t1.col70 > 1 and t1.col71 > 1 and t1.col72 > 1 and t1.col73 > 1 and t1.col74 > 1 and t1.col75 > 1 and t1.col76 > 1 and t1.col77 > 1 and t1.col78 > 1 and t1.col79 > 1 and t1.col80 > 1 and t1.col81 > 1 and t1.col82 > 1 and t1.col83 > 1 and t1.col84 > 1 and t1.col85 > 1 and t1.col86 > 1 and t1.col87 > 1 and t1.col88 > 1 and t1.col89 > 1 and t1.col90 > 1 and t1.col91 > 1 and t1.col92 > 1 and t1.col93 > 1 and t1.col94 > 1 and t1.col95 > 1 and t1.col96 > 1 and t1.col97 > 1 and t1.col98 > 1 and t1.col99 > 1 and t1.col100 > 1 and t1.col101 > 1 and t1.col102 > 1 and t1.col103 > 1 and t1.col104 > 1 and t1.col105 > 1 and t1.col106 > 1 and t1.col107 > 1 and t1.col108 > 1 and t1.col109 > 1 and t1.col110 > 1 and t1.col111 > 1 and t1.col112 > 1 and t1.col113 > 1 and t1.col114 > 1 and t1.col115 > 1 and t1.col116 > 1 and t1.col117 > 1 and t1.col118 > 1 and t1.col119 > 1 and t1.col120 > 1 and t1.col121 > 1 and t1.col122 > 1 and t1.col123 > 1 and t1.col124 > 1 and t1.col125 > 1 and t1.col126 > 1 and t1.col127 > 1 and t1.col128 > 1 and t1.col129 > 1 and t1.col130 > 1 and t1.col131 > 1 and t1.col132 > 1 and t1.col133 > 1 and t1.col134 > 1 and t1.col135 > 1 and t1.col136 > 1 and t1.col137 > 1 and t1.col138 > 1 and t1.col139 > 1 and t1.col140 > 1 and t1.col141 > 1 and t1.col142 > 1 and t1.col143 > 1 and t1.col144 > 1 and t1.col145 > 1 and t1.col146 > 1 and t1.col147 > 1 and t1.col148 > 1 and t1.col149 > 1 and t1.col150 > 1 and t1.col151 > 1 and t1.col152 > 1 and t1.col153 > 1 and t1.col154 > 1 and t1.col155 > 1 and t1.col156 > 1 and t1.col157 > 1 and t1.col158 > 1 and t1.col159 > 1"
}
}
]
}
}
select
json_detailed(json_extract(trace,'$**.selectivity_for_columns[0]')) as JS
from
information_schema.optimizer_trace;
JS
[
{
"column_name": "col0",
"ranges":
["1 < col0"],
"selectivity_from_histogram": 0.996078431
}
]
$query_tbl;
EXPLAIN
{
"query_block": {
"select_id": 1,
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 100,
"filtered": 53.32928848,
"attached_condition": "t1.col0 > 1 and t1.col1 > 1 and t1.col2 > 1 and t1.col3 > 1 and t1.col4 > 1 and t1.col5 > 1 and t1.col6 > 1 and t1.col7 > 1 and t1.col8 > 1 and t1.col9 > 1 and t1.col10 > 1 and t1.col11 > 1 and t1.col12 > 1 and t1.col13 > 1 and t1.col14 > 1 and t1.col15 > 1 and t1.col16 > 1 and t1.col17 > 1 and t1.col18 > 1 and t1.col19 > 1 and t1.col20 > 1 and t1.col21 > 1 and t1.col22 > 1 and t1.col23 > 1 and t1.col24 > 1 and t1.col25 > 1 and t1.col26 > 1 and t1.col27 > 1 and t1.col28 > 1 and t1.col29 > 1 and t1.col30 > 1 and t1.col31 > 1 and t1.col32 > 1 and t1.col33 > 1 and t1.col34 > 1 and t1.col35 > 1 and t1.col36 > 1 and t1.col37 > 1 and t1.col38 > 1 and t1.col39 > 1 and t1.col40 > 1 and t1.col41 > 1 and t1.col42 > 1 and t1.col43 > 1 and t1.col44 > 1 and t1.col45 > 1 and t1.col46 > 1 and t1.col47 > 1 and t1.col48 > 1 and t1.col49 > 1 and t1.col50 > 1 and t1.col51 > 1 and t1.col52 > 1 and t1.col53 > 1 and t1.col54 > 1 and t1.col55 > 1 and t1.col56 > 1 and t1.col57 > 1 and t1.col58 > 1 and t1.col59 > 1 and t1.col60 > 1 and t1.col61 > 1 and t1.col62 > 1 and t1.col63 > 1 and t1.col64 > 1 and t1.col65 > 1 and t1.col66 > 1 and t1.col67 > 1 and t1.col68 > 1 and t1.col69 > 1 and t1.col70 > 1 and t1.col71 > 1 and t1.col72 > 1 and t1.col73 > 1 and t1.col74 > 1 and t1.col75 > 1 and t1.col76 > 1 and t1.col77 > 1 and t1.col78 > 1 and t1.col79 > 1 and t1.col80 > 1 and t1.col81 > 1 and t1.col82 > 1 and t1.col83 > 1 and t1.col84 > 1 and t1.col85 > 1 and t1.col86 > 1 and t1.col87 > 1 and t1.col88 > 1 and t1.col89 > 1 and t1.col90 > 1 and t1.col91 > 1 and t1.col92 > 1 and t1.col93 > 1 and t1.col94 > 1 and t1.col95 > 1 and t1.col96 > 1 and t1.col97 > 1 and t1.col98 > 1 and t1.col99 > 1 and t1.col100 > 1 and t1.col101 > 1 and t1.col102 > 1 and t1.col103 > 1 and t1.col104 > 1 and t1.col105 > 1 and t1.col106 > 1 and t1.col107 > 1 and t1.col108 > 1 and t1.col109 > 1 and t1.col110 > 1 and t1.col111 > 1 and t1.col112 > 1 and t1.col113 > 1 and t1.col114 > 1 and t1.col115 > 1 and t1.col116 > 1 and t1.col117 > 1 and t1.col118 > 1 and t1.col119 > 1 and t1.col120 > 1 and t1.col121 > 1 and t1.col122 > 1 and t1.col123 > 1 and t1.col124 > 1 and t1.col125 > 1 and t1.col126 > 1 and t1.col127 > 1 and t1.col128 > 1 and t1.col129 > 1 and t1.col130 > 1 and t1.col131 > 1 and t1.col132 > 1 and t1.col133 > 1 and t1.col134 > 1 and t1.col135 > 1 and t1.col136 > 1 and t1.col137 > 1 and t1.col138 > 1 and t1.col139 > 1 and t1.col140 > 1 and t1.col141 > 1 and t1.col142 > 1 and t1.col143 > 1 and t1.col144 > 1 and t1.col145 > 1 and t1.col146 > 1 and t1.col147 > 1 and t1.col148 > 1 and t1.col149 > 1 and t1.col150 > 1 and t1.col151 > 1 and t1.col152 > 1 and t1.col153 > 1 and t1.col154 > 1 and t1.col155 > 1 and t1.col156 > 1 and t1.col157 > 1 and t1.col158 > 1 and t1.col159 > 1"
}
}
]
}
}
select
json_detailed(json_extract(trace,'$**.selectivity_for_columns[159]')) as JS
from
information_schema.optimizer_trace;
JS
[
{
"column_name": "col159",
"ranges":
["1 < col159"],
"selectivity_from_histogram": 0.996078431
}
]
#
# Check if not being able to infer anything for the first MAX_KEY
# columns doesn't prevent further inferences.
#
# explain extended select * from t1
# where (1>2 or col0>1 or col1>1 or ...) and col99>1
#
$query_tbl;
EXPLAIN
{
"query_block": {
"select_id": 1,
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 100,
"filtered": 99.60784149,
"attached_condition": "(t1.col1 > 1 or t1.col2 > 1 or t1.col3 > 1 or t1.col4 > 1 or t1.col5 > 1 or t1.col6 > 1 or t1.col7 > 1 or t1.col8 > 1 or t1.col9 > 1 or t1.col10 > 1 or t1.col11 > 1 or t1.col12 > 1 or t1.col13 > 1 or t1.col14 > 1 or t1.col15 > 1 or t1.col16 > 1 or t1.col17 > 1 or t1.col18 > 1 or t1.col19 > 1 or t1.col20 > 1 or t1.col21 > 1 or t1.col22 > 1 or t1.col23 > 1 or t1.col24 > 1 or t1.col25 > 1 or t1.col26 > 1 or t1.col27 > 1 or t1.col28 > 1 or t1.col29 > 1 or t1.col30 > 1 or t1.col31 > 1 or t1.col32 > 1 or t1.col33 > 1 or t1.col34 > 1 or t1.col35 > 1 or t1.col36 > 1 or t1.col37 > 1 or t1.col38 > 1 or t1.col39 > 1 or t1.col40 > 1 or t1.col41 > 1 or t1.col42 > 1 or t1.col43 > 1 or t1.col44 > 1 or t1.col45 > 1 or t1.col46 > 1 or t1.col47 > 1 or t1.col48 > 1 or t1.col49 > 1 or t1.col50 > 1 or t1.col51 > 1 or t1.col52 > 1 or t1.col53 > 1 or t1.col54 > 1 or t1.col55 > 1 or t1.col56 > 1 or t1.col57 > 1 or t1.col58 > 1 or t1.col59 > 1 or t1.col60 > 1 or t1.col61 > 1 or t1.col62 > 1 or t1.col63 > 1 or t1.col64 > 1 or t1.col65 > 1 or t1.col66 > 1 or t1.col67 > 1 or t1.col68 > 1 or t1.col69 > 1 or t1.col70 > 1 or t1.col71 > 1 or t1.col72 > 1 or t1.col73 > 1 or t1.col74 > 1 or t1.col75 > 1 or t1.col76 > 1 or t1.col77 > 1 or t1.col78 > 1 or t1.col79 > 1 or t1.col80 > 1 or t1.col81 > 1 or t1.col82 > 1 or t1.col83 > 1 or t1.col84 > 1 or t1.col85 > 1 or t1.col86 > 1 or t1.col87 > 1 or t1.col88 > 1 or t1.col89 > 1 or t1.col90 > 1 or t1.col91 > 1 or t1.col92 > 1 or t1.col93 > 1 or t1.col94 > 1 or t1.col95 > 1 or t1.col96 > 1 or t1.col97 > 1 or t1.col98 > 1 or t1.col99 > 1 or t1.col100 > 1 or t1.col101 > 1 or t1.col102 > 1 or t1.col103 > 1 or t1.col104 > 1 or t1.col105 > 1 or t1.col106 > 1 or t1.col107 > 1 or t1.col108 > 1 or t1.col109 > 1 or t1.col110 > 1 or t1.col111 > 1 or t1.col112 > 1 or t1.col113 > 1 or t1.col114 > 1 or t1.col115 > 1 or t1.col116 > 1 or t1.col117 > 1 or t1.col118 > 1 or t1.col119 > 1 or t1.col120 > 1 or t1.col121 > 1 or t1.col122 > 1 or t1.col123 > 1 or t1.col124 > 1 or t1.col125 > 1 or t1.col126 > 1 or t1.col127 > 1 or t1.col128 > 1 or t1.col129 > 1 or t1.col130 > 1 or t1.col131 > 1 or t1.col132 > 1 or t1.col133 > 1 or t1.col134 > 1 or t1.col135 > 1 or t1.col136 > 1 or t1.col137 > 1 or t1.col138 > 1 or t1.col139 > 1 or t1.col140 > 1 or t1.col141 > 1 or t1.col142 > 1 or t1.col143 > 1 or t1.col144 > 1 or t1.col145 > 1 or t1.col146 > 1 or t1.col147 > 1 or t1.col148 > 1 or t1.col149 > 1 or t1.col150 > 1 or t1.col151 > 1 or t1.col152 > 1 or t1.col153 > 1 or t1.col154 > 1 or t1.col155 > 1 or t1.col156 > 1 or t1.col157 > 1 or t1.col158 > 1) and t1.col159 > 1"
}
}
]
}
}
select
json_detailed(json_extract(trace,'$**.selectivity_for_columns')) as JS
from
information_schema.optimizer_trace;
JS
[
[
{
"column_name": "col159",
"ranges":
["1 < col159"],
"selectivity_from_histogram": 0.996078431
}
]
]
set optimizer_trace=@trace_tmp;
drop table t1;
#
# Clean up
#
set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
set use_stat_tables= @save_use_stat_tables;
set @@global.histogram_size=@save_histogram_size;
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
SET SESSION STORAGE_ENGINE=DEFAULT;

View File

@@ -83,13 +83,140 @@ sel
]
set optimizer_trace=@tmp;
drop table t0,t1,t10;
set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
set histogram_size=@save_histogram_size;
set use_stat_tables= @save_use_stat_tables;
#
# End of 10.4 tests
#
#
# MDEV-33314: Crash inside calculate_cond_selectivity_for_table() with many columns
#
set optimizer_use_condition_selectivity= 4;
set use_stat_tables= preferably;
#
# create table t1 (col0 int, col1 int, col2 int, ...);
#
$create_tbl;
#
# insert into t1 select seq, ... seq from seq_1_to_10;
#
$insert_cmd;
analyze table t1 persistent for all;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
set @trace_tmp=@@optimizer_trace;
set optimizer_trace=1;
#
# Basic testcase: don't crash for many-column selectivity
# explain extended select * from t1 where col0>1 and col1>1 and col2>1 and ...
#
$query_tbl;
EXPLAIN
{
"query_block": {
"select_id": 1,
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 100,
"filtered": 53.32928848,
"attached_condition": "t1.col0 > 1 and t1.col1 > 1 and t1.col2 > 1 and t1.col3 > 1 and t1.col4 > 1 and t1.col5 > 1 and t1.col6 > 1 and t1.col7 > 1 and t1.col8 > 1 and t1.col9 > 1 and t1.col10 > 1 and t1.col11 > 1 and t1.col12 > 1 and t1.col13 > 1 and t1.col14 > 1 and t1.col15 > 1 and t1.col16 > 1 and t1.col17 > 1 and t1.col18 > 1 and t1.col19 > 1 and t1.col20 > 1 and t1.col21 > 1 and t1.col22 > 1 and t1.col23 > 1 and t1.col24 > 1 and t1.col25 > 1 and t1.col26 > 1 and t1.col27 > 1 and t1.col28 > 1 and t1.col29 > 1 and t1.col30 > 1 and t1.col31 > 1 and t1.col32 > 1 and t1.col33 > 1 and t1.col34 > 1 and t1.col35 > 1 and t1.col36 > 1 and t1.col37 > 1 and t1.col38 > 1 and t1.col39 > 1 and t1.col40 > 1 and t1.col41 > 1 and t1.col42 > 1 and t1.col43 > 1 and t1.col44 > 1 and t1.col45 > 1 and t1.col46 > 1 and t1.col47 > 1 and t1.col48 > 1 and t1.col49 > 1 and t1.col50 > 1 and t1.col51 > 1 and t1.col52 > 1 and t1.col53 > 1 and t1.col54 > 1 and t1.col55 > 1 and t1.col56 > 1 and t1.col57 > 1 and t1.col58 > 1 and t1.col59 > 1 and t1.col60 > 1 and t1.col61 > 1 and t1.col62 > 1 and t1.col63 > 1 and t1.col64 > 1 and t1.col65 > 1 and t1.col66 > 1 and t1.col67 > 1 and t1.col68 > 1 and t1.col69 > 1 and t1.col70 > 1 and t1.col71 > 1 and t1.col72 > 1 and t1.col73 > 1 and t1.col74 > 1 and t1.col75 > 1 and t1.col76 > 1 and t1.col77 > 1 and t1.col78 > 1 and t1.col79 > 1 and t1.col80 > 1 and t1.col81 > 1 and t1.col82 > 1 and t1.col83 > 1 and t1.col84 > 1 and t1.col85 > 1 and t1.col86 > 1 and t1.col87 > 1 and t1.col88 > 1 and t1.col89 > 1 and t1.col90 > 1 and t1.col91 > 1 and t1.col92 > 1 and t1.col93 > 1 and t1.col94 > 1 and t1.col95 > 1 and t1.col96 > 1 and t1.col97 > 1 and t1.col98 > 1 and t1.col99 > 1 and t1.col100 > 1 and t1.col101 > 1 and t1.col102 > 1 and t1.col103 > 1 and t1.col104 > 1 and t1.col105 > 1 and t1.col106 > 1 and t1.col107 > 1 and t1.col108 > 1 and t1.col109 > 1 and t1.col110 > 1 and t1.col111 > 1 and t1.col112 > 1 and t1.col113 > 1 and t1.col114 > 1 and t1.col115 > 1 and t1.col116 > 1 and t1.col117 > 1 and t1.col118 > 1 and t1.col119 > 1 and t1.col120 > 1 and t1.col121 > 1 and t1.col122 > 1 and t1.col123 > 1 and t1.col124 > 1 and t1.col125 > 1 and t1.col126 > 1 and t1.col127 > 1 and t1.col128 > 1 and t1.col129 > 1 and t1.col130 > 1 and t1.col131 > 1 and t1.col132 > 1 and t1.col133 > 1 and t1.col134 > 1 and t1.col135 > 1 and t1.col136 > 1 and t1.col137 > 1 and t1.col138 > 1 and t1.col139 > 1 and t1.col140 > 1 and t1.col141 > 1 and t1.col142 > 1 and t1.col143 > 1 and t1.col144 > 1 and t1.col145 > 1 and t1.col146 > 1 and t1.col147 > 1 and t1.col148 > 1 and t1.col149 > 1 and t1.col150 > 1 and t1.col151 > 1 and t1.col152 > 1 and t1.col153 > 1 and t1.col154 > 1 and t1.col155 > 1 and t1.col156 > 1 and t1.col157 > 1 and t1.col158 > 1 and t1.col159 > 1"
}
}
]
}
}
select
json_detailed(json_extract(trace,'$**.selectivity_for_columns[0]')) as JS
from
information_schema.optimizer_trace;
JS
[
{
"column_name": "col0",
"ranges":
["1 < col0"],
"selectivity_from_histogram": 0.996078431
}
]
$query_tbl;
EXPLAIN
{
"query_block": {
"select_id": 1,
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 100,
"filtered": 53.32928848,
"attached_condition": "t1.col0 > 1 and t1.col1 > 1 and t1.col2 > 1 and t1.col3 > 1 and t1.col4 > 1 and t1.col5 > 1 and t1.col6 > 1 and t1.col7 > 1 and t1.col8 > 1 and t1.col9 > 1 and t1.col10 > 1 and t1.col11 > 1 and t1.col12 > 1 and t1.col13 > 1 and t1.col14 > 1 and t1.col15 > 1 and t1.col16 > 1 and t1.col17 > 1 and t1.col18 > 1 and t1.col19 > 1 and t1.col20 > 1 and t1.col21 > 1 and t1.col22 > 1 and t1.col23 > 1 and t1.col24 > 1 and t1.col25 > 1 and t1.col26 > 1 and t1.col27 > 1 and t1.col28 > 1 and t1.col29 > 1 and t1.col30 > 1 and t1.col31 > 1 and t1.col32 > 1 and t1.col33 > 1 and t1.col34 > 1 and t1.col35 > 1 and t1.col36 > 1 and t1.col37 > 1 and t1.col38 > 1 and t1.col39 > 1 and t1.col40 > 1 and t1.col41 > 1 and t1.col42 > 1 and t1.col43 > 1 and t1.col44 > 1 and t1.col45 > 1 and t1.col46 > 1 and t1.col47 > 1 and t1.col48 > 1 and t1.col49 > 1 and t1.col50 > 1 and t1.col51 > 1 and t1.col52 > 1 and t1.col53 > 1 and t1.col54 > 1 and t1.col55 > 1 and t1.col56 > 1 and t1.col57 > 1 and t1.col58 > 1 and t1.col59 > 1 and t1.col60 > 1 and t1.col61 > 1 and t1.col62 > 1 and t1.col63 > 1 and t1.col64 > 1 and t1.col65 > 1 and t1.col66 > 1 and t1.col67 > 1 and t1.col68 > 1 and t1.col69 > 1 and t1.col70 > 1 and t1.col71 > 1 and t1.col72 > 1 and t1.col73 > 1 and t1.col74 > 1 and t1.col75 > 1 and t1.col76 > 1 and t1.col77 > 1 and t1.col78 > 1 and t1.col79 > 1 and t1.col80 > 1 and t1.col81 > 1 and t1.col82 > 1 and t1.col83 > 1 and t1.col84 > 1 and t1.col85 > 1 and t1.col86 > 1 and t1.col87 > 1 and t1.col88 > 1 and t1.col89 > 1 and t1.col90 > 1 and t1.col91 > 1 and t1.col92 > 1 and t1.col93 > 1 and t1.col94 > 1 and t1.col95 > 1 and t1.col96 > 1 and t1.col97 > 1 and t1.col98 > 1 and t1.col99 > 1 and t1.col100 > 1 and t1.col101 > 1 and t1.col102 > 1 and t1.col103 > 1 and t1.col104 > 1 and t1.col105 > 1 and t1.col106 > 1 and t1.col107 > 1 and t1.col108 > 1 and t1.col109 > 1 and t1.col110 > 1 and t1.col111 > 1 and t1.col112 > 1 and t1.col113 > 1 and t1.col114 > 1 and t1.col115 > 1 and t1.col116 > 1 and t1.col117 > 1 and t1.col118 > 1 and t1.col119 > 1 and t1.col120 > 1 and t1.col121 > 1 and t1.col122 > 1 and t1.col123 > 1 and t1.col124 > 1 and t1.col125 > 1 and t1.col126 > 1 and t1.col127 > 1 and t1.col128 > 1 and t1.col129 > 1 and t1.col130 > 1 and t1.col131 > 1 and t1.col132 > 1 and t1.col133 > 1 and t1.col134 > 1 and t1.col135 > 1 and t1.col136 > 1 and t1.col137 > 1 and t1.col138 > 1 and t1.col139 > 1 and t1.col140 > 1 and t1.col141 > 1 and t1.col142 > 1 and t1.col143 > 1 and t1.col144 > 1 and t1.col145 > 1 and t1.col146 > 1 and t1.col147 > 1 and t1.col148 > 1 and t1.col149 > 1 and t1.col150 > 1 and t1.col151 > 1 and t1.col152 > 1 and t1.col153 > 1 and t1.col154 > 1 and t1.col155 > 1 and t1.col156 > 1 and t1.col157 > 1 and t1.col158 > 1 and t1.col159 > 1"
}
}
]
}
}
select
json_detailed(json_extract(trace,'$**.selectivity_for_columns[159]')) as JS
from
information_schema.optimizer_trace;
JS
[
{
"column_name": "col159",
"ranges":
["1 < col159"],
"selectivity_from_histogram": 0.996078431
}
]
#
# Check if not being able to infer anything for the first MAX_KEY
# columns doesn't prevent further inferences.
#
# explain extended select * from t1
# where (1>2 or col0>1 or col1>1 or ...) and col99>1
#
$query_tbl;
EXPLAIN
{
"query_block": {
"select_id": 1,
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 100,
"filtered": 99.60784149,
"attached_condition": "(t1.col1 > 1 or t1.col2 > 1 or t1.col3 > 1 or t1.col4 > 1 or t1.col5 > 1 or t1.col6 > 1 or t1.col7 > 1 or t1.col8 > 1 or t1.col9 > 1 or t1.col10 > 1 or t1.col11 > 1 or t1.col12 > 1 or t1.col13 > 1 or t1.col14 > 1 or t1.col15 > 1 or t1.col16 > 1 or t1.col17 > 1 or t1.col18 > 1 or t1.col19 > 1 or t1.col20 > 1 or t1.col21 > 1 or t1.col22 > 1 or t1.col23 > 1 or t1.col24 > 1 or t1.col25 > 1 or t1.col26 > 1 or t1.col27 > 1 or t1.col28 > 1 or t1.col29 > 1 or t1.col30 > 1 or t1.col31 > 1 or t1.col32 > 1 or t1.col33 > 1 or t1.col34 > 1 or t1.col35 > 1 or t1.col36 > 1 or t1.col37 > 1 or t1.col38 > 1 or t1.col39 > 1 or t1.col40 > 1 or t1.col41 > 1 or t1.col42 > 1 or t1.col43 > 1 or t1.col44 > 1 or t1.col45 > 1 or t1.col46 > 1 or t1.col47 > 1 or t1.col48 > 1 or t1.col49 > 1 or t1.col50 > 1 or t1.col51 > 1 or t1.col52 > 1 or t1.col53 > 1 or t1.col54 > 1 or t1.col55 > 1 or t1.col56 > 1 or t1.col57 > 1 or t1.col58 > 1 or t1.col59 > 1 or t1.col60 > 1 or t1.col61 > 1 or t1.col62 > 1 or t1.col63 > 1 or t1.col64 > 1 or t1.col65 > 1 or t1.col66 > 1 or t1.col67 > 1 or t1.col68 > 1 or t1.col69 > 1 or t1.col70 > 1 or t1.col71 > 1 or t1.col72 > 1 or t1.col73 > 1 or t1.col74 > 1 or t1.col75 > 1 or t1.col76 > 1 or t1.col77 > 1 or t1.col78 > 1 or t1.col79 > 1 or t1.col80 > 1 or t1.col81 > 1 or t1.col82 > 1 or t1.col83 > 1 or t1.col84 > 1 or t1.col85 > 1 or t1.col86 > 1 or t1.col87 > 1 or t1.col88 > 1 or t1.col89 > 1 or t1.col90 > 1 or t1.col91 > 1 or t1.col92 > 1 or t1.col93 > 1 or t1.col94 > 1 or t1.col95 > 1 or t1.col96 > 1 or t1.col97 > 1 or t1.col98 > 1 or t1.col99 > 1 or t1.col100 > 1 or t1.col101 > 1 or t1.col102 > 1 or t1.col103 > 1 or t1.col104 > 1 or t1.col105 > 1 or t1.col106 > 1 or t1.col107 > 1 or t1.col108 > 1 or t1.col109 > 1 or t1.col110 > 1 or t1.col111 > 1 or t1.col112 > 1 or t1.col113 > 1 or t1.col114 > 1 or t1.col115 > 1 or t1.col116 > 1 or t1.col117 > 1 or t1.col118 > 1 or t1.col119 > 1 or t1.col120 > 1 or t1.col121 > 1 or t1.col122 > 1 or t1.col123 > 1 or t1.col124 > 1 or t1.col125 > 1 or t1.col126 > 1 or t1.col127 > 1 or t1.col128 > 1 or t1.col129 > 1 or t1.col130 > 1 or t1.col131 > 1 or t1.col132 > 1 or t1.col133 > 1 or t1.col134 > 1 or t1.col135 > 1 or t1.col136 > 1 or t1.col137 > 1 or t1.col138 > 1 or t1.col139 > 1 or t1.col140 > 1 or t1.col141 > 1 or t1.col142 > 1 or t1.col143 > 1 or t1.col144 > 1 or t1.col145 > 1 or t1.col146 > 1 or t1.col147 > 1 or t1.col148 > 1 or t1.col149 > 1 or t1.col150 > 1 or t1.col151 > 1 or t1.col152 > 1 or t1.col153 > 1 or t1.col154 > 1 or t1.col155 > 1 or t1.col156 > 1 or t1.col157 > 1 or t1.col158 > 1) and t1.col159 > 1"
}
}
]
}
}
select
json_detailed(json_extract(trace,'$**.selectivity_for_columns')) as JS
from
information_schema.optimizer_trace;
JS
[
[
{
"column_name": "col159",
"ranges":
["1 < col159"],
"selectivity_from_histogram": 0.996078431
}
]
]
set optimizer_trace=@trace_tmp;
drop table t1;
#
# Clean up
#
set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
set use_stat_tables= @save_use_stat_tables;
set @@global.histogram_size=@save_histogram_size;

View File

@@ -105,17 +105,113 @@ from information_schema.optimizer_trace;
set optimizer_trace=@tmp;
drop table t0,t1,t10;
set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
set histogram_size=@save_histogram_size;
set use_stat_tables= @save_use_stat_tables;
--echo #
--echo # End of 10.4 tests
--echo #
--echo #
--echo # MDEV-33314: Crash inside calculate_cond_selectivity_for_table() with many columns
--echo #
set optimizer_use_condition_selectivity= 4;
set use_stat_tables= preferably;
let $N_CONDS=160;
let $N_LAST_COND=159;
--echo #
--echo # create table t1 (col0 int, col1 int, col2 int, ...);
--echo #
let $create_tbl= create table t1 ( col0 int;
let $i=1;
while ($i < $N_CONDS) {
let $create_tbl= $create_tbl, col$i int;
let $i=`select $i + 1`;
}
let $create_tbl= $create_tbl );
#echo $create_tbl;
evalp $create_tbl;
--echo #
--echo # insert into t1 select seq, ... seq from seq_1_to_10;
--echo #
let $insert_cmd= insert into t1 select seq;
let $i=1;
while ($i < $N_CONDS) {
let $insert_cmd = $insert_cmd ,seq;
let $i=`select $i + 1`;
}
let $insert_cmd= $insert_cmd from seq_1_to_100;
# echo $insert_cmd;
evalp $insert_cmd;
analyze table t1 persistent for all;
set @trace_tmp=@@optimizer_trace;
set optimizer_trace=1;
--echo #
--echo # Basic testcase: don't crash for many-column selectivity
--echo # explain extended select * from t1 where col0>1 and col1>1 and col2>1 and ...
--echo #
let $query_tbl= explain format=json select * from t1 where col0>1;
let $i=1;
while ($i < $N_CONDS) {
let $query_tbl= $query_tbl and col$i>1;
let $i=`select $i + 1`;
}
#echo $query_tbl;
evalp $query_tbl;
select
json_detailed(json_extract(trace,'$**.selectivity_for_columns[0]')) as JS
from
information_schema.optimizer_trace;
evalp $query_tbl;
eval select
json_detailed(json_extract(trace,'\$**.selectivity_for_columns[$N_LAST_COND]')) as JS
from
information_schema.optimizer_trace;
--echo #
--echo # Check if not being able to infer anything for the first MAX_KEY
--echo # columns doesn't prevent further inferences.
--echo #
--echo # explain extended select * from t1
--echo # where (1>2 or col0>1 or col1>1 or ...) and col99>1
--echo #
let $query_tbl= explain format=json select * from t1 where (1>2 ;
let $i=1;
while ($i < $N_LAST_COND) {
let $query_tbl= $query_tbl or col$i>1;
let $i=`select $i + 1`;
}
let $query_tbl= $query_tbl) and col$N_LAST_COND>1;
#echo $query_tbl;
evalp $query_tbl;
select
json_detailed(json_extract(trace,'$**.selectivity_for_columns')) as JS
from
information_schema.optimizer_trace;
set optimizer_trace=@trace_tmp;
drop table t1;
--echo #
--echo # Clean up
--echo #
--source include/restore_charset.inc
set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
set use_stat_tables= @save_use_stat_tables;
set @@global.histogram_size=@save_histogram_size;

View File

@@ -3101,7 +3101,7 @@ sub mysql_install_db {
mtr_add_arg($args, "--core-file");
mtr_add_arg($args, "--console");
mtr_add_arg($args, "--character-set-server=latin1");
mtr_add_arg($args, "--disable-performance-schema");
mtr_add_arg($args, "--loose-disable-performance-schema");
if ( $opt_debug )
{

Binary file not shown.

Binary file not shown.

View File

@@ -23,6 +23,15 @@ insert into t2 select * from t1;
insert into t3 select * from t1;
insert into t4 select * from t1;
commit;
# Flush all dirty pages from buffer pool
SET @no_checkpoint_save_pct= @@GLOBAL.innodb_max_dirty_pages_pct;
SET @no_checkpoint_save_pct_lwm= @@GLOBAL.innodb_max_dirty_pages_pct_lwm;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
SET GLOBAL innodb_max_dirty_pages_pct= @no_checkpoint_save_pct;
SET GLOBAL innodb_max_dirty_pages_pct_lwm= @no_checkpoint_save_pct_lwm;
CREATE TABLE t5 (a VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES;
SET GLOBAL innodb_flush_log_at_trx_commit=1;
begin;
@@ -42,6 +51,6 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
FOUND 1 /\[ERROR\] InnoDB: Encryption key is not found for .*test.t1.ibd/ in mysqld.1.err
FOUND 1 /\[ERROR\] InnoDB: Encryption key is not found for .*test.t[1-5].ibd/ in mysqld.1.err
# restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt
drop table t1,t2,t3,t4,t5;

View File

@@ -44,7 +44,9 @@ insert into t3 select * from t1;
insert into t4 select * from t1;
commit;
let $no_checkpoint_flush= 1;
--source ../../suite/innodb/include/no_checkpoint_start.inc
#
# We test redo log page read at recv_read_page using
# keys that are not in std_data/keys.txt. If checkpoint
@@ -77,7 +79,7 @@ WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err;
let SEARCH_PATTERN = \[ERROR\] InnoDB: Encryption key is not found for .*test.t1.ibd;
let SEARCH_PATTERN = \[ERROR\] InnoDB: Encryption key is not found for .*test.t[1-5].ibd;
--source include/search_pattern_in_file.inc
#

View File

@@ -521,6 +521,23 @@ use federated;
SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3
WHERE id=2) dt2) dt;
id name
PREPARE stmt FROM "
SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3
WHERE id=3) dt2) dt;
";
EXECUTE stmt;
id name
3 xxx
EXECUTE stmt;
id name
3 xxx
DEALLOCATE PREPARE stmt;
EXPLAIN
SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3
WHERE id=3) dt2) dt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 5 Using where
4 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
connection slave;
CREATE TABLE federated.t10 (a INT,b INT);
CREATE TABLE federated.t11 (a INT, b INT);
@@ -541,6 +558,54 @@ WHERE id=2) dt2) dt
a b a b id name
1 1 NULL NULL NULL NULL
2 2 NULL NULL NULL NULL
#
# MDEV-31361: Second execution of PS for query with derived table
#
connection slave;
DROP TABLE IF EXISTS federated.t1;
CREATE TABLE federated.t1 (
id int(20) NOT NULL,
name varchar(16) NOT NULL default ''
)
DEFAULT CHARSET=latin1;
INSERT INTO federated.t1 VALUES
(3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy');
connection master;
DROP TABLE IF EXISTS federated.t1;
CREATE TABLE federated.t1 (
id int(20) NOT NULL,
name varchar(16) NOT NULL default ''
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
use federated;
SELECT * FROM
(SELECT * FROM
(SELECT * FROM
(SELECT * FROM t1 where id>3) dt3
WHERE id>3) dt2
) dt;
id name
7 yyy
4 xxx
5 yyy
PREPARE stmt FROM "SELECT * FROM
(SELECT * FROM
(SELECT * FROM
(SELECT * FROM t1 where id>3) dt3
WHERE id>3) dt2
) dt";
EXECUTE stmt;
id name
7 yyy
4 xxx
5 yyy
EXECUTE stmt;
id name
7 yyy
4 xxx
5 yyy
DEALLOCATE PREPARE stmt;
set global federated_pushdown=0;
connection master;
DROP TABLE IF EXISTS federated.t1;

View File

@@ -94,12 +94,9 @@ DEFAULT CHARSET=latin1;
INSERT INTO federated.t3 VALUES
('yyy'), ('www'), ('yyy'), ('xxx'), ('www'), ('yyy'), ('www');
#Enable after fix MDEV-31361
--disable_ps2_protocol
SELECT *
FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
WHERE federated.t3.name=t.name;
--enable_ps2_protocol
EXPLAIN
SELECT *
@@ -354,6 +351,18 @@ use federated;
SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3
WHERE id=2) dt2) dt;
PREPARE stmt FROM "
SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3
WHERE id=3) dt2) dt;
";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
EXPLAIN
SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3
WHERE id=3) dt2) dt;
connection slave;
CREATE TABLE federated.t10 (a INT,b INT);
CREATE TABLE federated.t11 (a INT, b INT);
@@ -379,6 +388,52 @@ SELECT * FROM t10 LEFT JOIN
WHERE id=2) dt2) dt
) ON t10.a=t11.a;
--echo #
--echo # MDEV-31361: Second execution of PS for query with derived table
--echo #
connection slave;
DROP TABLE IF EXISTS federated.t1;
CREATE TABLE federated.t1 (
id int(20) NOT NULL,
name varchar(16) NOT NULL default ''
)
DEFAULT CHARSET=latin1;
INSERT INTO federated.t1 VALUES
(3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy');
connection master;
DROP TABLE IF EXISTS federated.t1;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval
CREATE TABLE federated.t1 (
id int(20) NOT NULL,
name varchar(16) NOT NULL default ''
)
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
use federated;
let $q=
SELECT * FROM
(SELECT * FROM
(SELECT * FROM
(SELECT * FROM t1 where id>3) dt3
WHERE id>3) dt2
) dt;
eval $q;
eval PREPARE stmt FROM "$q";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set global federated_pushdown=0;
source include/federated_cleanup.inc;

View File

@@ -0,0 +1,211 @@
connection node_2;
connection node_1;
#
# MDEV-33355 Add a Galera-2-node-to-MariaDB replication MTR test cloning the slave with mariadb-backup
#
connect master, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connect slave, 127.0.0.1, root, , test, $NODE_MYPORT_3;
START SLAVE;
include/wait_for_slave_to_start.inc
connection master;
connection slave;
##############################################################
### Initial block with some transactions
### Slave: Make sure replication is not using GTID
connection slave;
# Using_Gtid=No
### Master: Create and populate t1
connection master;
CREATE TABLE t1(a TEXT) ENGINE=InnoDB;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#00:stmt#00 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#00:stmt#01 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#00:stmt#02 - slave run#0, before backup');
COMMIT;
connection slave;
##############################################################
### Run the last transaction before mariadb-backup --backup
### Remember SHOW MASTER STATUS and @@gtid_binlog_pos
### before and after the transaction.
### Master: Rember MASTER STATUS and @@gtid_binlog_pos before tr#01
connection master;
### Slave: Remember MASTER STATUS and @@gtid_binlog_pos before tr#01
connection slave;
### Master: Run the actual last transaction before the backup
connection master;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#01:stmt#00 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#01:stmt#01 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#01:stmt#02 - slave run#0, before backup');
COMMIT;
connection slave;
### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01
connection master;
### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01
connection slave;
##############################################################
### Running `mariadb-backup --backup,--prepare` and checking
### that xtrabackup_slave_info and xtrabackup_binlog_info are OK
### Slave: Create a backup
### Slave: Prepare the backup
### Slave: xtrabackup files:
############################ xtrabackup_slave_info
CHANGE MASTER TO MASTER_LOG_FILE='master_after_tr01_show_master_status_file', MASTER_LOG_POS=master_after_tr01_show_master_status_position;
############################ xtrabackup_binlog_info
slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_position slave_after_tr01_gtid_binlog_pos
############################
##############################################################
### Run more transactions after the backup:
### - while the slave is still running, then
### - while the slave is shut down
### Master: Run another transaction while the slave is still running
connection master;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup');
INSERT INTO t1 VALUES ('tr#02:stmt#01 - slave run#0, after backup');
INSERT INTO t1 VALUES ('tr#02:stmt@02 - slave run#0, after backup');
COMMIT;
connection slave;
### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02
connection master;
### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02
connection slave;
### Master: Checking SHOW BINLOG EVENTS
connection master;
SHOW BINLOG EVENTS IN 'master_after_tr01_show_master_status_file' FROM master_after_tr01_show_master_status_position LIMIT 0,1;
Log_name master_after_tr01_show_master_status_file
Pos master_after_tr01_show_master_status_position
Event_type Gtid
Server_id #
End_log_pos #
Info BEGIN GTID master_after_tr02_gtid_binlog_pos
SHOW BINLOG EVENTS IN 'master_after_tr01_show_master_status_file' FROM master_after_tr01_show_master_status_position LIMIT 1,1;
Log_name master_after_tr01_show_master_status_file
Pos #
Event_type Query_or_Annotate_rows
Server_id #
End_log_pos #
Info INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup')
### Slave: Checking SHOW BINLOG EVENTS
connection slave;
SHOW BINLOG EVENTS IN 'slave_after_tr01_show_master_status_file' FROM slave_after_tr01_show_master_status_position LIMIT 0,1;
Log_name slave_after_tr01_show_master_status_file
Pos #
Event_type Gtid
Server_id 1
End_log_pos #
Info BEGIN GTID slave_after_tr02_gtid_binlog_pos
SHOW BINLOG EVENTS IN 'slave_after_tr01_show_master_status_file' FROM slave_after_tr01_show_master_status_position LIMIT 1,1;
Log_name slave_after_tr01_show_master_status_file
Pos #
Event_type Query_or_Annotate_rows
Server_id #
End_log_pos #
Info INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup')
### Slave: Stop replication
connection slave;
STOP SLAVE;
include/wait_for_slave_to_stop.inc
RESET SLAVE;
Warnings:
Note 4190 RESET SLAVE is implicitly changing the value of 'Using_Gtid' from 'No' to 'Slave_Pos'
### Slave: Shutdown the server
connection slave;
### Master: Run a transaction while the slave is shut down
connection master;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#03:stmt#00 - after slave run#0, slave is shut down, after backup');
INSERT INTO t1 VALUES ('tr#03:stmt#01 - after slave run#0, slave is shut down, after backup');
INSERT INTO t1 VALUES ('tr#03:stmt#02 - after slave run#0, slave is shut down, after backup');
COMMIT;
##############################################################
### Emulate starting a new virgin slave
### Slave: Remove the data directory
### Slave: Copy back the backup
### Slave: Restart the server
connection slave;
# restart
### Slave: Display the restored data before START SLAVE
connection slave;
SELECT * FROM t1 ORDER BY a;
a
tr#00:stmt#00 - slave run#0, before backup
tr#00:stmt#01 - slave run#0, before backup
tr#00:stmt#02 - slave run#0, before backup
tr#01:stmt#00 - slave run#0, before backup
tr#01:stmt#01 - slave run#0, before backup
tr#01:stmt#02 - slave run#0, before backup
### Slave: Execute the CHANGE MASTER statement to set up the host and port
CHANGE MASTER '' TO MASTER_USER='root', MASTER_HOST='127.0.0.1', MASTER_PORT=###, MASTER_CONNECT_RETRY=1;
### Slave: Execute the CHANGE MASTER statement from xtrabackup_slave_info
CHANGE MASTER TO MASTER_LOG_FILE='master_after_tr01_show_master_status_file', MASTER_LOG_POS=master_after_tr01_show_master_status_position;
Warnings:
Note 4190 CHANGE MASTER TO is implicitly changing the value of 'Using_Gtid' from 'Slave_Pos' to 'No'
### Slave: Execute START SLAVE
include/start_slave.inc
### Master: Wait for the slave to apply all master events
connection master;
connection slave;
### Slave: Make sure replication is not using GTID after the slave restart
connection slave;
# Using_Gtid=No
### Slave: Display the restored data after START SLAVE
connection slave;
SELECT * FROM t1 ORDER BY a;
a
tr#00:stmt#00 - slave run#0, before backup
tr#00:stmt#01 - slave run#0, before backup
tr#00:stmt#02 - slave run#0, before backup
tr#01:stmt#00 - slave run#0, before backup
tr#01:stmt#01 - slave run#0, before backup
tr#01:stmt#02 - slave run#0, before backup
tr#02:stmt#00 - slave run#0, after backup
tr#02:stmt#01 - slave run#0, after backup
tr#02:stmt@02 - slave run#0, after backup
tr#03:stmt#00 - after slave run#0, slave is shut down, after backup
tr#03:stmt#01 - after slave run#0, slave is shut down, after backup
tr#03:stmt#02 - after slave run#0, slave is shut down, after backup
##############################################################
### Continue master transactions, check the new slave replicates well.
### Master: Run a transaction after restarting replication
connection master;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#04:stmt#00 - slave run#1');
INSERT INTO t1 VALUES ('tr#04:stmt#01 - slave run#1');
INSERT INTO t1 VALUES ('tr#04:stmt#02 - slave run#1');
COMMIT;
connection slave;
### Slave: Display the restored data + new transactions
connection slave;
SELECT * FROM t1 ORDER BY a;
a
tr#00:stmt#00 - slave run#0, before backup
tr#00:stmt#01 - slave run#0, before backup
tr#00:stmt#02 - slave run#0, before backup
tr#01:stmt#00 - slave run#0, before backup
tr#01:stmt#01 - slave run#0, before backup
tr#01:stmt#02 - slave run#0, before backup
tr#02:stmt#00 - slave run#0, after backup
tr#02:stmt#01 - slave run#0, after backup
tr#02:stmt@02 - slave run#0, after backup
tr#03:stmt#00 - after slave run#0, slave is shut down, after backup
tr#03:stmt#01 - after slave run#0, slave is shut down, after backup
tr#03:stmt#02 - after slave run#0, slave is shut down, after backup
tr#04:stmt#00 - slave run#1
tr#04:stmt#01 - slave run#1
tr#04:stmt#02 - slave run#1
##############################################################
### Cleanup
### Removing the backup directory
connection master;
DROP TABLE t1;
connection slave;
STOP SLAVE;
include/wait_for_slave_to_stop.inc
RESET SLAVE ALL;
Warnings:
Note 4190 RESET SLAVE is implicitly changing the value of 'Using_Gtid' from 'No' to 'Slave_Pos'
connection master;
set global wsrep_on=OFF;
RESET MASTER;
set global wsrep_on=ON;

View File

@@ -0,0 +1 @@
!include ../galera_2nodes_as_master.cnf

View File

@@ -0,0 +1,9 @@
--source include/have_innodb.inc
--source include/galera_cluster.inc
--echo #
--echo # MDEV-33355 Add a Galera-2-node-to-MariaDB replication MTR test cloning the slave with mariadb-backup
--echo #
--let cnf=galera2_to_mariadb
--source include/rpl_clone_slave_using_mariadb-backup.inc

View File

@@ -1,5 +1,28 @@
# Preparation for using no_checkpoint_end.inc
# no_checkpoint_flush: Set to trigger flushing the dirty pages from buffer pool
# and checkpoint before the "no checkpoint" block.
if ($no_checkpoint_flush) {
--echo
--echo # Flush all dirty pages from buffer pool
SET @no_checkpoint_save_pct= @@GLOBAL.innodb_max_dirty_pages_pct;
SET @no_checkpoint_save_pct_lwm= @@GLOBAL.innodb_max_dirty_pages_pct_lwm;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
let $wait_condition =
SELECT variable_value = 0
FROM information_schema.global_status
WHERE variable_name = 'INNODB_BUFFER_POOL_PAGES_DIRTY';
--source include/wait_condition.inc
SET GLOBAL innodb_max_dirty_pages_pct= @no_checkpoint_save_pct;
SET GLOBAL innodb_max_dirty_pages_pct_lwm= @no_checkpoint_save_pct_lwm;
--echo
}
let MYSQLD_DATADIR= `select @@datadir`;
--replace_regex /.*Last checkpoint at[ ]*([0-9]+).*/\1/
let CHECKPOINT_LSN=`SHOW ENGINE INNODB STATUS`;

View File

@@ -0,0 +1,232 @@
CREATE TABLE t1 (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(42);
CREATE TABLE t1b LIKE t1;
INSERT INTO t1b VALUES(3);
CREATE TABLE t1z LIKE t1;
CREATE TABLE t1t (id TINYINT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t0t LIKE t1t;
INSERT INTO t1t VALUES(123);
FLUSH TABLES t1,t1b,t1t FOR EXPORT;
UNLOCK TABLES;
CREATE TABLE t5_7 LIKE t1;
CREATE TABLE t5_7b LIKE t1b;
CREATE TABLE t10_1 LIKE t1;
CREATE TABLE t10_1b LIKE t1b;
ALTER TABLE t1 DISCARD TABLESPACE;
ALTER TABLE t1b DISCARD TABLESPACE;
ALTER TABLE t1z DISCARD TABLESPACE;
ALTER TABLE t1t DISCARD TABLESPACE;
ALTER TABLE t0t DISCARD TABLESPACE;
ALTER TABLE t5_7 DISCARD TABLESPACE;
ALTER TABLE t5_7b DISCARD TABLESPACE;
ALTER TABLE t10_1 DISCARD TABLESPACE;
ALTER TABLE t10_1b DISCARD TABLESPACE;
FLUSH TABLES;
ALTER TABLE t0t IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t0t.cfg', will attempt to import without schema verification
INSERT INTO t0t VALUES(NULL);
SELECT * FROM t0t;
id
123
124
DROP TABLE t0t;
ALTER TABLE t1 IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1.cfg', will attempt to import without schema verification
ALTER TABLE t1b IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1b.cfg', will attempt to import without schema verification
ALTER TABLE t1z IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1z.cfg', will attempt to import without schema verification
ALTER TABLE t1t IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1t.cfg', will attempt to import without schema verification
ALTER TABLE t5_7 IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t5_7.cfg', will attempt to import without schema verification
ALTER TABLE t5_7b IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t5_7b.cfg', will attempt to import without schema verification
ALTER TABLE t10_1 IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t10_1.cfg', will attempt to import without schema verification
ALTER TABLE t10_1b IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t10_1b.cfg', will attempt to import without schema verification
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t0t`/ in mysqld.1.err
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 0 to 42 on table `test`\.`t1z`/ in mysqld.1.err
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t1t`/ in mysqld.1.err
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t5_7` \(created with version 50744\)/ in mysqld.1.err
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t10_1` \(created with version 100149\)/ in mysqld.1.err
FOUND 5 /InnoDB: Resetting PAGE_ROOT_AUTO_INC/ in mysqld.1.err
# restart: --read-only
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t5_7 check status OK
test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t5_7b check status OK
test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t10_1 check status OK
test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t10_1b check status OK
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t5_7 check status OK
test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t5_7b check status OK
test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t10_1 check status OK
test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t10_1b check status OK
# restart: --innodb-read-only --read-only
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t5_7 check status OK
test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t5_7b check status OK
test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t10_1 check status OK
test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t10_1b check status OK
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t5_7 check status OK
test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t5_7b check status OK
test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t10_1 check status OK
test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
test.t10_1b check status OK
# restart: --innodb-read-only
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check status Operation failed
test.t5_7b check status Operation failed
test.t10_1 check status Operation failed
test.t10_1b check status Operation failed
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check status Operation failed
test.t5_7b check status Operation failed
test.t10_1 check status Operation failed
test.t10_1b check status Operation failed
SELECT COUNT(*) FROM t1;
COUNT(*)
1
SELECT COUNT(*) FROM t1b;
COUNT(*)
1
SELECT COUNT(*) FROM t1t;
COUNT(*)
1
SELECT COUNT(*) FROM t1z;
COUNT(*)
1
SELECT COUNT(*) FROM t5_7;
COUNT(*)
1
SELECT COUNT(*) FROM t5_7b;
COUNT(*)
1
SELECT COUNT(*) FROM t10_1;
COUNT(*)
1
SELECT COUNT(*) FROM t10_1b;
COUNT(*)
1
# restart
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check note Auto_increment checked and .frm file version updated
test.t5_7 check status OK
test.t5_7b check note Auto_increment checked and .frm file version updated
test.t5_7b check status OK
test.t10_1 check note Auto_increment checked and .frm file version updated
test.t10_1 check status OK
test.t10_1b check note Auto_increment checked and .frm file version updated
test.t10_1b check status OK
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1b VALUES(NULL);
INSERT INTO t1t VALUES(NULL);
INSERT INTO t1z VALUES(NULL);
INSERT INTO t5_7 VALUES(NULL);
INSERT INTO t5_7b VALUES(NULL);
INSERT INTO t10_1 VALUES(NULL);
INSERT INTO t10_1b VALUES(NULL);
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t1b check status OK
test.t1t check status OK
test.t1z check status OK
test.t5_7 check status OK
test.t5_7b check status OK
test.t10_1 check status OK
test.t10_1b check status OK
SELECT * FROM t1;
id
4
42
SELECT * FROM t1b;
id
3
347
SELECT * FROM t1t;
id
123
124
SELECT * FROM t1z;
id
42
43
SELECT * FROM t5_7;
id
42
43
SELECT * FROM t5_7b;
id
3
347
SELECT * FROM t10_1;
id
42
43
SELECT * FROM t10_1b;
id
3
347
DROP TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;

View File

@@ -1035,9 +1035,22 @@ BEGIN;
INSERT INTO child SET a=1;
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`))
connection default;
TRUNCATE TABLE parent;
ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`parent` (`a`))
DROP TABLE parent;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
SET innodb_lock_wait_timeout=0;
RENAME TABLE parent TO transparent;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
ALTER TABLE parent FORCE, ALGORITHM=COPY;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
SET innodb_lock_wait_timeout=0, foreign_key_checks=0;
TRUNCATE TABLE parent;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
DROP TABLE parent;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
ALTER TABLE parent FORCE, ALGORITHM=COPY;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
@@ -1052,7 +1065,13 @@ TRUNCATE TABLE parent;
ALTER TABLE parent FORCE, ALGORITHM=COPY;
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
ALTER TABLE parent ADD COLUMN b INT, ALGORITHM=INSTANT;
DROP TABLE child, parent;
SET foreign_key_checks=ON;
TRUNCATE TABLE parent;
ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`parent` (`a`))
ALTER TABLE parent FORCE, ALGORITHM=COPY;
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
RENAME TABLE parent TO transparent;
DROP TABLE child, transparent;
#
# MDEV-26217 Failing assertion: list.count > 0 in ut_list_remove
# or Assertion `lock->trx == this' failed in dberr_t trx_t::drop_table

View File

@@ -50,7 +50,15 @@ t1 CREATE TABLE `t1` (
`b` blob DEFAULT NULL,
`c` blob DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC
) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC
# Auto increment value must be more than maximum column value
SELECT MAX(a) FROM t1;
MAX(a)
45
SELECT auto_increment FROM information_schema.tables
WHERE table_name like 't1';
auto_increment
46
UPDATE t1 set b = repeat("de", 100) where b = repeat("cd", 200);
explain SELECT a FROM t1 where b = repeat("de", 100);
id select_type table type possible_keys key key_len ref rows Extra
@@ -132,7 +140,15 @@ t1 CREATE TABLE `t1` (
`c2` point NOT NULL,
`c3` linestring NOT NULL,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=16372 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC
) ENGINE=InnoDB AUTO_INCREMENT=14325 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC
# Auto increment value must be more than maximum column value
SELECT MAX(c1) FROM t1;
MAX(c1)
14324
SELECT auto_increment FROM information_schema.tables
WHERE table_name like 't1';
auto_increment
14325
UPDATE t1 SET C2 = ST_GeomFromText('POINT(0 0)');
SELECT COUNT(*) FROM t1;
COUNT(*)

View File

@@ -15,6 +15,41 @@ CREATE TABLE imp_t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
DROP TABLE imp_t1, t1;
SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm;
#
# MDEV-18288: Transportable Tablespaces leave AUTO_INCREMENT in mismatched
# state, causing INSERT errors in newly imported tables when .cfg is not used.
#
CREATE TABLE t1(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE t2 LIKE t1;
ALTER TABLE t2 DISCARD TABLESPACE;
INSERT INTO t1() VALUES();
INSERT INTO t1() VALUES();
FLUSH TABLES test.t1 FOR EXPORT;
# Copy data file
# Skip CFG file copy
UNLOCK TABLES;
DROP TABLE t1;
ALTER TABLE t2 IMPORT TABLESPACE;
Warnings:
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t2.cfg', will attempt to import without schema verification
SELECT * FROM t2 ORDER BY id;
id
1
2
INSERT INTO t2() VALUES();
INSERT INTO t2() VALUES();
INSERT INTO t2() VALUES();
SELECT * FROM t2 ORDER BY id;
id
1
2
3
4
5
DROP TABLE t2;
#
# MDEV-27006 Assertion `!lock_trx_has_sys_table_locks(trx)'
# failed in dberr_t row_discard_tablespace_for_mysql
# (dict_table_t*, trx_t*)

View File

@@ -1,5 +0,0 @@
CREATE TABLE t (c INT) ENGINE=INNODB;
SET @save_dbug = @@debug_dbug;
SET debug_dbug = '+d,test_ut_format_name';
DROP TABLE t;
SET debug_dbug = @save_dbug;

View File

@@ -4,15 +4,14 @@ Variable_name Value
innodb_doublewrite ON
create table t1(f1 int not null, f2 int not null)engine=innodb;
insert into t1 values (1, 1);
InnoDB 0 transactions not purged
set GLOBAL innodb_log_checkpoint_now=1;
SET GLOBAL innodb_fast_shutdown = 0;
# restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0
# Make the first page dirty for undo tablespace
set global innodb_saved_page_number_debug = 0;
set global innodb_fil_make_page_dirty_debug = 1;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
SET GLOBAL innodb_buf_flush_list_now = 1;
# Kill the server
# restart
# restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0
FOUND 1 /Checksum mismatch in the first page of file/ in mysqld.1.err
check table t1;
Table Op Msg_type Msg_text

View File

@@ -0,0 +1,168 @@
--source include/have_innodb.inc
CREATE TABLE t1 (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(42);
CREATE TABLE t1b LIKE t1;
INSERT INTO t1b VALUES(3);
CREATE TABLE t1z LIKE t1;
CREATE TABLE t1t (id TINYINT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t0t LIKE t1t;
INSERT INTO t1t VALUES(123);
--let DATADIR=`select @@datadir`
--let PAGE_SIZE=`select @@innodb_page_size`
FLUSH TABLES t1,t1b,t1t FOR EXPORT;
--copy_file $DATADIR/test/t1.ibd $DATADIR/test/t.ibd
--copy_file $DATADIR/test/t1.ibd $DATADIR/test/tz.ibd
--copy_file $DATADIR/test/t1b.ibd $DATADIR/test/tb.ibd
--copy_file $DATADIR/test/t1t.ibd $DATADIR/test/tt.ibd
UNLOCK TABLES;
CREATE TABLE t5_7 LIKE t1;
CREATE TABLE t5_7b LIKE t1b;
CREATE TABLE t10_1 LIKE t1;
CREATE TABLE t10_1b LIKE t1b;
ALTER TABLE t1 DISCARD TABLESPACE;
ALTER TABLE t1b DISCARD TABLESPACE;
ALTER TABLE t1z DISCARD TABLESPACE;
ALTER TABLE t1t DISCARD TABLESPACE;
ALTER TABLE t0t DISCARD TABLESPACE;
ALTER TABLE t5_7 DISCARD TABLESPACE;
ALTER TABLE t5_7b DISCARD TABLESPACE;
ALTER TABLE t10_1 DISCARD TABLESPACE;
ALTER TABLE t10_1b DISCARD TABLESPACE;
FLUSH TABLES;
# Update the PAGE_ROOT_AUTO_INC field of a few files.
perl;
do "$ENV{MTR_SUITE_DIR}/include/crc32.pl";
sub update_autoinc
{
my ($file, $value) = @_;
open(FILE, "+<$file") || die "Unable to open $file";
binmode FILE;
my $ps= $ENV{PAGE_SIZE};
my $page;
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
my $full_crc32 = unpack("N",substr($page,54,4)) & 0x10; # FIL_SPACE_FLAGS
sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n";
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
substr($page,56,8)=pack("NN",0,$value);
my $polynomial = 0x82f63b78; # CRC-32C
if ($full_crc32) {
my $ck = mycrc32(substr($page, 0, $ps-4), 0, $polynomial);
substr($page, $ps-4, 4) = pack("N", $ck);
}
else
{
my $ck= pack("N",mycrc32(substr($page, 4, 22), 0, $polynomial) ^
mycrc32(substr($page, 38, $ps - 38 - 8), 0, $polynomial));
substr($page,0,4)=$ck;
substr($page,$ps-8,4)=$ck;
}
sysseek(FILE, 3*$ps, 0) || die "Unable to rewind $file\n";
syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n";
close(FILE) || die "Unable to close $file";
}
update_autoinc("$ENV{DATADIR}/test/tz.ibd", 0);
update_autoinc("$ENV{DATADIR}/test/t.ibd", 3);
update_autoinc("$ENV{DATADIR}/test/tb.ibd", 346);
update_autoinc("$ENV{DATADIR}/test/tt.ibd", 128);
EOF
--remove_file $DATADIR/test/t5_7.frm
--remove_file $DATADIR/test/t5_7b.frm
--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_57.frm $DATADIR/test/t5_7.frm
--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_57.frm $DATADIR/test/t5_7b.frm
--remove_file $DATADIR/test/t10_1.frm
--remove_file $DATADIR/test/t10_1b.frm
--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_101.frm $DATADIR/test/t10_1.frm
--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_101.frm $DATADIR/test/t10_1b.frm
--copy_file $DATADIR/test/t.ibd $DATADIR/test/t5_7.ibd
--copy_file $DATADIR/test/tb.ibd $DATADIR/test/t5_7b.ibd
--copy_file $DATADIR/test/t.ibd $DATADIR/test/t10_1.ibd
--copy_file $DATADIR/test/tb.ibd $DATADIR/test/t10_1b.ibd
--move_file $DATADIR/test/t.ibd $DATADIR/test/t1.ibd
--move_file $DATADIR/test/tb.ibd $DATADIR/test/t1b.ibd
--copy_file $DATADIR/test/tt.ibd $DATADIR/test/t0t.ibd
--move_file $DATADIR/test/tt.ibd $DATADIR/test/t1t.ibd
--move_file $DATADIR/test/tz.ibd $DATADIR/test/t1z.ibd
ALTER TABLE t0t IMPORT TABLESPACE;
INSERT INTO t0t VALUES(NULL);
SELECT * FROM t0t;
DROP TABLE t0t;
ALTER TABLE t1 IMPORT TABLESPACE;
ALTER TABLE t1b IMPORT TABLESPACE;
ALTER TABLE t1z IMPORT TABLESPACE;
ALTER TABLE t1t IMPORT TABLESPACE;
ALTER TABLE t5_7 IMPORT TABLESPACE;
ALTER TABLE t5_7b IMPORT TABLESPACE;
ALTER TABLE t10_1 IMPORT TABLESPACE;
ALTER TABLE t10_1b IMPORT TABLESPACE;
--let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t0t`
--source include/search_pattern_in_file.inc
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 0 to 42 on table `test`\.`t1z`
--source include/search_pattern_in_file.inc
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t1t`
--source include/search_pattern_in_file.inc
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t5_7` \(created with version 50744\)
--source include/search_pattern_in_file.inc
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t10_1` \(created with version 100149\)
--source include/search_pattern_in_file.inc
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC
--source include/search_pattern_in_file.inc
# Restart, so that the InnoDB tables will be loaded into the data dictionary.
--let $restart_parameters=--read-only
--source include/restart_mysqld.inc
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
--let $restart_parameters=--innodb-read-only --read-only
--source include/restart_mysqld.inc
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
--let $restart_parameters=--innodb-read-only
--source include/restart_mysqld.inc
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
SELECT COUNT(*) FROM t1;
SELECT COUNT(*) FROM t1b;
SELECT COUNT(*) FROM t1t;
SELECT COUNT(*) FROM t1z;
SELECT COUNT(*) FROM t5_7;
SELECT COUNT(*) FROM t5_7b;
SELECT COUNT(*) FROM t10_1;
SELECT COUNT(*) FROM t10_1b;
--let $restart_parameters=
--source include/restart_mysqld.inc
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1b VALUES(NULL);
INSERT INTO t1t VALUES(NULL);
INSERT INTO t1z VALUES(NULL);
INSERT INTO t5_7 VALUES(NULL);
INSERT INTO t5_7b VALUES(NULL);
INSERT INTO t10_1 VALUES(NULL);
INSERT INTO t10_1b VALUES(NULL);
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
SELECT * FROM t1;
SELECT * FROM t1b;
SELECT * FROM t1t;
SELECT * FROM t1z;
SELECT * FROM t5_7;
SELECT * FROM t5_7b;
SELECT * FROM t10_1;
SELECT * FROM t10_1b;
DROP TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;

View File

@@ -1077,10 +1077,23 @@ BEGIN;
--error ER_NO_REFERENCED_ROW_2
INSERT INTO child SET a=1;
connection default;
--error ER_TRUNCATE_ILLEGAL_FK
TRUNCATE TABLE parent;
--error ER_ROW_IS_REFERENCED_2
DROP TABLE parent;
SET innodb_lock_wait_timeout=0;
--error ER_LOCK_WAIT_TIMEOUT
RENAME TABLE parent TO transparent;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE parent FORCE, ALGORITHM=COPY;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
SET innodb_lock_wait_timeout=0, foreign_key_checks=0;
--error ER_LOCK_WAIT_TIMEOUT
TRUNCATE TABLE parent;
--error ER_LOCK_WAIT_TIMEOUT
DROP TABLE parent;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE parent FORCE, ALGORITHM=COPY;
--error ER_LOCK_WAIT_TIMEOUT
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
@@ -1095,7 +1108,13 @@ TRUNCATE TABLE parent;
ALTER TABLE parent FORCE, ALGORITHM=COPY;
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
ALTER TABLE parent ADD COLUMN b INT, ALGORITHM=INSTANT;
DROP TABLE child, parent;
SET foreign_key_checks=ON;
--error ER_TRUNCATE_ILLEGAL_FK
TRUNCATE TABLE parent;
ALTER TABLE parent FORCE, ALGORITHM=COPY;
ALTER TABLE parent FORCE, ALGORITHM=INPLACE;
RENAME TABLE parent TO transparent;
DROP TABLE child, transparent;
--echo #
--echo # MDEV-26217 Failing assertion: list.count > 0 in ut_list_remove

View File

@@ -63,6 +63,12 @@ ALTER TABLE t1 DROP INDEX b;
ALTER TABLE t1 IMPORT TABLESPACE;
--enable_warnings
SHOW CREATE TABLE t1;
--echo # Auto increment value must be more than maximum column value
SELECT MAX(a) FROM t1;
SELECT auto_increment FROM information_schema.tables
WHERE table_name like 't1';
UPDATE t1 set b = repeat("de", 100) where b = repeat("cd", 200);
--replace_column 9 #
explain SELECT a FROM t1 where b = repeat("de", 100);
@@ -145,6 +151,12 @@ ALTER TABLE t1 DROP INDEX idx1;
ALTER TABLE t1 IMPORT TABLESPACE;
--disable_warnings
SHOW CREATE TABLE t1;
--echo # Auto increment value must be more than maximum column value
SELECT MAX(c1) FROM t1;
SELECT auto_increment FROM information_schema.tables
WHERE table_name like 't1';
UPDATE t1 SET C2 = ST_GeomFromText('POINT(0 0)');
SELECT COUNT(*) FROM t1;
DELETE FROM t1;

View File

@@ -22,6 +22,47 @@ DROP TABLE imp_t1, t1;
SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm;
--echo #
--echo # MDEV-18288: Transportable Tablespaces leave AUTO_INCREMENT in mismatched
--echo # state, causing INSERT errors in newly imported tables when .cfg is not used.
--echo #
CREATE TABLE t1(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE t2 LIKE t1;
ALTER TABLE t2 DISCARD TABLESPACE;
INSERT INTO t1() VALUES();
INSERT INTO t1() VALUES();
FLUSH TABLES test.t1 FOR EXPORT;
--echo # Copy data file
--copy_file $datadir/test/t1.ibd $datadir/test/t2.ibd
--echo # Skip CFG file copy
#--copy_file $datadir/test/t1.cfg $datadir/test/t2.cfg
--remove_file $datadir/test/t1.cfg
UNLOCK TABLES;
DROP TABLE t1;
--replace_regex /opening '.*\/test\//opening '.\/test\//
ALTER TABLE t2 IMPORT TABLESPACE;
SELECT * FROM t2 ORDER BY id;
INSERT INTO t2() VALUES();
INSERT INTO t2() VALUES();
INSERT INTO t2() VALUES();
SELECT * FROM t2 ORDER BY id;
DROP TABLE t2;
--echo #
--echo # MDEV-27006 Assertion `!lock_trx_has_sys_table_locks(trx)'
--echo # failed in dberr_t row_discard_tablespace_for_mysql

View File

@@ -1,17 +0,0 @@
#
# Test ut_format_name()
#
-- source include/have_debug.inc
-- source include/have_innodb.inc
CREATE TABLE t (c INT) ENGINE=INNODB;
# This will invoke test_ut_format_name() in debug builds
SET @save_dbug = @@debug_dbug;
SET debug_dbug = '+d,test_ut_format_name';
DROP TABLE t;
SET debug_dbug = @save_dbug;

View File

@@ -9,19 +9,19 @@ show variables like 'innodb_doublewrite';
create table t1(f1 int not null, f2 int not null)engine=innodb;
insert into t1 values (1, 1);
--source include/wait_all_purged.inc
# Slow shutdown and restart to make sure ibuf merge is finished
SET GLOBAL innodb_fast_shutdown = 0;
let $shutdown_timeout=;
let $restart_parameters="--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0";
--source include/restart_mysqld.inc
set GLOBAL innodb_log_checkpoint_now=1;
--source ../include/no_checkpoint_start.inc
--echo # Make the first page dirty for undo tablespace
set global innodb_saved_page_number_debug = 0;
set global innodb_fil_make_page_dirty_debug = 1;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
SET GLOBAL innodb_buf_flush_list_now = 1;
sleep 1;
--let CLEANUP_IF_CHECKPOINT=drop table t1;
--source ../include/no_checkpoint_end.inc

View File

@@ -14,6 +14,14 @@ ALTER TABLE t1 IMPORT TABLESPACE;
SELECT * FROM t1;
i
1
# MDEV-33023 Crash in mariadb-backup --prepare --export after --prepare
t1.cfg
t21.cfg
ALTER TABLE t1 DISCARD TABLESPACE;
ALTER TABLE t1 IMPORT TABLESPACE;
SELECT * FROM t1;
i
1
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t21;

View File

@@ -55,6 +55,25 @@ copy_file $targetdir/test/t1.cfg $MYSQLD_DATADIR/test/t1.cfg;
ALTER TABLE t1 IMPORT TABLESPACE;
SELECT * FROM t1;
--echo # MDEV-33023 Crash in mariadb-backup --prepare --export after --prepare
--disable_result_log
exec $XTRABACKUP --defaults-file=$server_cnf --defaults-group-suffix=.1 --prepare --target-dir=$targetdir;
exec $XTRABACKUP --defaults-file=$server_cnf --defaults-group-suffix=.1 --prepare --export --target-dir=$targetdir;
--enable_result_log
list_files $targetdir/test *.cfg;
# There must not be binary logs created on --prepare step
list_files $targetdir/ mysqld-bin.*;
let $MYSQLD_DATADIR= `select @@datadir`;
ALTER TABLE t1 DISCARD TABLESPACE;
copy_file $targetdir/test/t1.ibd $MYSQLD_DATADIR/test/t1.ibd;
copy_file $targetdir/test/t1.cfg $MYSQLD_DATADIR/test/t1.cfg;
ALTER TABLE t1 IMPORT TABLESPACE;
SELECT * FROM t1;
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t21;

View File

@@ -0,0 +1,202 @@
include/master-slave.inc
[connection master]
#
# MDEV-33342 Add a replication MTR test cloning the slave with mariadb-backup
#
connection slave;
stop slave;
change master to master_use_gtid=no;
start slave;
connection master;
connection slave;
##############################################################
### Initial block with some transactions
### Slave: Make sure replication is not using GTID
connection slave;
# Using_Gtid=No
### Master: Create and populate t1
connection master;
CREATE TABLE t1(a TEXT) ENGINE=InnoDB;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#00:stmt#00 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#00:stmt#01 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#00:stmt#02 - slave run#0, before backup');
COMMIT;
connection slave;
##############################################################
### Run the last transaction before mariadb-backup --backup
### Remember SHOW MASTER STATUS and @@gtid_binlog_pos
### before and after the transaction.
### Master: Rember MASTER STATUS and @@gtid_binlog_pos before tr#01
connection master;
### Slave: Remember MASTER STATUS and @@gtid_binlog_pos before tr#01
connection slave;
### Master: Run the actual last transaction before the backup
connection master;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#01:stmt#00 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#01:stmt#01 - slave run#0, before backup');
INSERT INTO t1 VALUES ('tr#01:stmt#02 - slave run#0, before backup');
COMMIT;
connection slave;
### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01
connection master;
### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01
connection slave;
##############################################################
### Running `mariadb-backup --backup,--prepare` and checking
### that xtrabackup_slave_info and xtrabackup_binlog_info are OK
### Slave: Create a backup
### Slave: Prepare the backup
### Slave: xtrabackup files:
############################ xtrabackup_slave_info
CHANGE MASTER TO MASTER_LOG_FILE='master_after_tr01_show_master_status_file', MASTER_LOG_POS=master_after_tr01_show_master_status_position;
############################ xtrabackup_binlog_info
slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_position slave_after_tr01_gtid_binlog_pos
############################
##############################################################
### Run more transactions after the backup:
### - while the slave is still running, then
### - while the slave is shut down
### Master: Run another transaction while the slave is still running
connection master;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup');
INSERT INTO t1 VALUES ('tr#02:stmt#01 - slave run#0, after backup');
INSERT INTO t1 VALUES ('tr#02:stmt@02 - slave run#0, after backup');
COMMIT;
connection slave;
### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02
connection master;
### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02
connection slave;
### Master: Checking SHOW BINLOG EVENTS
connection master;
SHOW BINLOG EVENTS IN 'master_after_tr01_show_master_status_file' FROM master_after_tr01_show_master_status_position LIMIT 0,1;
Log_name master_after_tr01_show_master_status_file
Pos master_after_tr01_show_master_status_position
Event_type Gtid
Server_id #
End_log_pos #
Info BEGIN GTID master_after_tr02_gtid_binlog_pos
SHOW BINLOG EVENTS IN 'master_after_tr01_show_master_status_file' FROM master_after_tr01_show_master_status_position LIMIT 1,1;
Log_name master_after_tr01_show_master_status_file
Pos #
Event_type Query_or_Annotate_rows
Server_id #
End_log_pos #
Info INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup')
### Slave: Checking SHOW BINLOG EVENTS
connection slave;
SHOW BINLOG EVENTS IN 'slave_after_tr01_show_master_status_file' FROM slave_after_tr01_show_master_status_position LIMIT 0,1;
Log_name slave_after_tr01_show_master_status_file
Pos #
Event_type Gtid
Server_id 1
End_log_pos #
Info BEGIN GTID slave_after_tr02_gtid_binlog_pos
SHOW BINLOG EVENTS IN 'slave_after_tr01_show_master_status_file' FROM slave_after_tr01_show_master_status_position LIMIT 1,1;
Log_name slave_after_tr01_show_master_status_file
Pos #
Event_type Query_or_Annotate_rows
Server_id #
End_log_pos #
Info INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup')
### Slave: Stop replication
connection slave;
STOP SLAVE;
include/wait_for_slave_to_stop.inc
RESET SLAVE;
Warnings:
Note 4190 RESET SLAVE is implicitly changing the value of 'Using_Gtid' from 'No' to 'Slave_Pos'
### Slave: Shutdown the server
include/rpl_stop_server.inc [server_number=2]
### Master: Run a transaction while the slave is shut down
connection master;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#03:stmt#00 - after slave run#0, slave is shut down, after backup');
INSERT INTO t1 VALUES ('tr#03:stmt#01 - after slave run#0, slave is shut down, after backup');
INSERT INTO t1 VALUES ('tr#03:stmt#02 - after slave run#0, slave is shut down, after backup');
COMMIT;
##############################################################
### Emulate starting a new virgin slave
### Slave: Remove the data directory
### Slave: Copy back the backup
### Slave: Restart the server
include/rpl_start_server.inc [server_number=2]
### Slave: Display the restored data before START SLAVE
connection slave;
SELECT * FROM t1 ORDER BY a;
a
tr#00:stmt#00 - slave run#0, before backup
tr#00:stmt#01 - slave run#0, before backup
tr#00:stmt#02 - slave run#0, before backup
tr#01:stmt#00 - slave run#0, before backup
tr#01:stmt#01 - slave run#0, before backup
tr#01:stmt#02 - slave run#0, before backup
### Slave: Execute the CHANGE MASTER statement to set up the host and port
CHANGE MASTER '' TO MASTER_USER='root', MASTER_HOST='127.0.0.1', MASTER_PORT=###, MASTER_CONNECT_RETRY=1;
### Slave: Execute the CHANGE MASTER statement from xtrabackup_slave_info
CHANGE MASTER TO MASTER_LOG_FILE='master_after_tr01_show_master_status_file', MASTER_LOG_POS=master_after_tr01_show_master_status_position;
Warnings:
Note 4190 CHANGE MASTER TO is implicitly changing the value of 'Using_Gtid' from 'Slave_Pos' to 'No'
### Slave: Execute START SLAVE
include/start_slave.inc
### Master: Wait for the slave to apply all master events
connection master;
connection slave;
### Slave: Make sure replication is not using GTID after the slave restart
connection slave;
# Using_Gtid=No
### Slave: Display the restored data after START SLAVE
connection slave;
SELECT * FROM t1 ORDER BY a;
a
tr#00:stmt#00 - slave run#0, before backup
tr#00:stmt#01 - slave run#0, before backup
tr#00:stmt#02 - slave run#0, before backup
tr#01:stmt#00 - slave run#0, before backup
tr#01:stmt#01 - slave run#0, before backup
tr#01:stmt#02 - slave run#0, before backup
tr#02:stmt#00 - slave run#0, after backup
tr#02:stmt#01 - slave run#0, after backup
tr#02:stmt@02 - slave run#0, after backup
tr#03:stmt#00 - after slave run#0, slave is shut down, after backup
tr#03:stmt#01 - after slave run#0, slave is shut down, after backup
tr#03:stmt#02 - after slave run#0, slave is shut down, after backup
##############################################################
### Continue master transactions, check the new slave replicates well.
### Master: Run a transaction after restarting replication
connection master;
START TRANSACTION;
INSERT INTO t1 VALUES ('tr#04:stmt#00 - slave run#1');
INSERT INTO t1 VALUES ('tr#04:stmt#01 - slave run#1');
INSERT INTO t1 VALUES ('tr#04:stmt#02 - slave run#1');
COMMIT;
connection slave;
### Slave: Display the restored data + new transactions
connection slave;
SELECT * FROM t1 ORDER BY a;
a
tr#00:stmt#00 - slave run#0, before backup
tr#00:stmt#01 - slave run#0, before backup
tr#00:stmt#02 - slave run#0, before backup
tr#01:stmt#00 - slave run#0, before backup
tr#01:stmt#01 - slave run#0, before backup
tr#01:stmt#02 - slave run#0, before backup
tr#02:stmt#00 - slave run#0, after backup
tr#02:stmt#01 - slave run#0, after backup
tr#02:stmt@02 - slave run#0, after backup
tr#03:stmt#00 - after slave run#0, slave is shut down, after backup
tr#03:stmt#01 - after slave run#0, slave is shut down, after backup
tr#03:stmt#02 - after slave run#0, slave is shut down, after backup
tr#04:stmt#00 - slave run#1
tr#04:stmt#01 - slave run#1
tr#04:stmt#02 - slave run#1
##############################################################
### Cleanup
### Removing the backup directory
connection master;
DROP TABLE t1;
connection slave;
include/rpl_end.inc

View File

@@ -0,0 +1,17 @@
#
# Cloning a slave using mariadb-backup
#
--source include/have_innodb.inc
--source include/master-slave.inc
--echo #
--echo # MDEV-33342 Add a replication MTR test cloning the slave with mariadb-backup
--echo #
connection slave;
stop slave;
change master to master_use_gtid=no;
start slave;
--let cnf=mariadb_to_mariadb
--source include/rpl_clone_slave_using_mariadb-backup.inc

View File

@@ -449,3 +449,85 @@ VALUES
('2000-01-01 00:00:00.000000', '2001-01-01 00:00:00.000000', 'abc');
ERROR 23000: Duplicate entry 'abc-2001-01-01 00:00:00.000000-2000-01-01 00:00:00.000000' for key 'index_name'
DROP TABLE t1;
# MDEV-25370 Update for portion changes autoincrement key in period table
create or replace table cars(id int auto_increment,
price int, s date, e date,
period for p(s,e),
primary key(id, p without overlaps));
insert into cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
select * from cars;
id price s e
1 1000 2018-01-01 2020-01-01
update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100;
select * from cars;
id price s e
1 1000 2018-01-01 2019-01-01
1 1000 2019-12-01 2020-01-01
1 1100 2019-01-01 2019-12-01
delete from cars for portion of p from '2019-12-10' to '2019-12-20';
select * from cars;
id price s e
1 1000 2018-01-01 2019-01-01
1 1000 2019-12-01 2019-12-10
1 1000 2019-12-20 2020-01-01
1 1100 2019-01-01 2019-12-01
# AUTO_INCREMENT field is separate from WITHOUT OVERLAPS
create or replace table cars(id int primary key auto_increment,
car_id int,
price int, s date, e date,
period for p(s,e),
unique(car_id, p without overlaps));
insert cars(car_id, price, s, e) values (1, 1000, '2018-01-01', '2020-01-01');
select * from cars;
id car_id price s e
1 1 1000 2018-01-01 2020-01-01
update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100;
select * from cars;
id car_id price s e
1 1 1100 2019-01-01 2019-12-01
2 1 1000 2018-01-01 2019-01-01
3 1 1000 2019-12-01 2020-01-01
delete from cars for portion of p from '2019-12-10' to '2019-12-20';
select * from cars;
id car_id price s e
1 1 1100 2019-01-01 2019-12-01
2 1 1000 2018-01-01 2019-01-01
4 1 1000 2019-12-01 2019-12-10
5 1 1000 2019-12-20 2020-01-01
# AUTO_INCREMENT field is both standalone and in WITHOUT OVERLAPS
create or replace table cars(id int primary key auto_increment,
price int, s date, e date,
period for p(s,e),
unique(id, p without overlaps));
insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
insert cars(price, s, e) values (1000, '2021-01-01', '2022-01-01');
update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100;
# autoincrement index is: id int primary key
# id increments each time.
select * from cars;
id price s e
1 1100 2019-01-01 2019-12-01
2 1000 2021-01-01 2022-01-01
3 1000 2018-01-01 2019-01-01
4 1000 2019-12-01 2020-01-01
truncate cars;
insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
delete from cars for portion of p from '2019-12-10' to '2019-12-20';
select * from cars;
id price s e
2 1000 2018-01-01 2019-12-10
3 1000 2019-12-20 2020-01-01
create or replace table cars(id int unique auto_increment,
price int, s date, e date,
period for p(s,e),
primary key (id, p without overlaps));
insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
# autoincrement index is: primary key (id, p without overlaps)
# id is not incremented, hence duplication error
update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100;
ERROR 23000: Duplicate entry '1' for key 'id'
truncate cars;
insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
delete from cars for portion of p from '2019-12-10' to '2019-12-20';
ERROR 23000: Duplicate entry '1' for key 'id'
drop table cars;

View File

@@ -458,3 +458,80 @@ VALUES
('2000-01-01 00:00:00.000000', '2001-01-01 00:00:00.000000', 'abc '),
('2000-01-01 00:00:00.000000', '2001-01-01 00:00:00.000000', 'abc');
DROP TABLE t1;
--echo # MDEV-25370 Update for portion changes autoincrement key in period table
create or replace table cars(id int auto_increment,
price int, s date, e date,
period for p(s,e),
primary key(id, p without overlaps));
insert into cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
select * from cars;
update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100;
--sorted_result
select * from cars;
delete from cars for portion of p from '2019-12-10' to '2019-12-20';
--sorted_result
select * from cars;
--echo # AUTO_INCREMENT field is separate from WITHOUT OVERLAPS
create or replace table cars(id int primary key auto_increment,
car_id int,
price int, s date, e date,
period for p(s,e),
unique(car_id, p without overlaps));
insert cars(car_id, price, s, e) values (1, 1000, '2018-01-01', '2020-01-01');
select * from cars;
update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100;
--sorted_result
select * from cars;
delete from cars for portion of p from '2019-12-10' to '2019-12-20';
--sorted_result
select * from cars;
--echo # AUTO_INCREMENT field is both standalone and in WITHOUT OVERLAPS
create or replace table cars(id int primary key auto_increment,
price int, s date, e date,
period for p(s,e),
unique(id, p without overlaps));
insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
insert cars(price, s, e) values (1000, '2021-01-01', '2022-01-01');
update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100;
--echo # autoincrement index is: id int primary key
--echo # id increments each time.
--sorted_result
select * from cars;
truncate cars;
insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
delete from cars for portion of p from '2019-12-10' to '2019-12-20';
--sorted_result
select * from cars;
create or replace table cars(id int unique auto_increment,
price int, s date, e date,
period for p(s,e),
primary key (id, p without overlaps));
insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
--echo # autoincrement index is: primary key (id, p without overlaps)
--echo # id is not incremented, hence duplication error
--error ER_DUP_ENTRY
update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100;
truncate cars;
insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01');
--error ER_DUP_ENTRY
delete from cars for portion of p from '2019-12-10' to '2019-12-20';
drop table cars;

View File

@@ -22,7 +22,4 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
set global innodb_saved_page_number_debug = 0;
set global innodb_fil_make_page_dirty_debug = @space_id;
drop table t1;
# Must always be 0.
SELECT @@global.innodb_fil_make_page_dirty_debug;
@@global.innodb_fil_make_page_dirty_debug
0
set global innodb_fil_make_page_dirty_debug = 0;

View File

@@ -23,6 +23,7 @@ set global innodb_saved_page_number_debug = 0;
set global innodb_fil_make_page_dirty_debug = @space_id;
drop table t1;
set global innodb_saved_page_number_debug = 0;
set global innodb_fil_make_page_dirty_debug = 0;
SELECT @@global.innodb_saved_page_number_debug;
@@global.innodb_saved_page_number_debug
0

View File

@@ -31,6 +31,4 @@ set global innodb_saved_page_number_debug = 0;
set global innodb_fil_make_page_dirty_debug = @space_id;
drop table t1;
--echo # Must always be 0.
SELECT @@global.innodb_fil_make_page_dirty_debug;
set global innodb_fil_make_page_dirty_debug = 0;

View File

@@ -32,6 +32,7 @@ set global innodb_fil_make_page_dirty_debug = @space_id;
drop table t1;
set global innodb_saved_page_number_debug = 0;
set global innodb_fil_make_page_dirty_debug = 0;
SELECT @@global.innodb_saved_page_number_debug;

View File

@@ -32,11 +32,12 @@ IF (HAVE_ALLOCA_H AND HAVE_CRACK_H AND HAVE_LIBCRACK AND HAVE_MEMCPY)
IF(CHECKMODULE AND SEMODULE_PACKAGE)
FOREACH(pol mariadb-plugin-cracklib-password-check)
SET(src ${CMAKE_CURRENT_SOURCE_DIR}/policy/selinux/${pol}.te)
SET(tmp ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${pol}-pp.dir/${pol}.mod)
SET(tmp ${CMAKE_CURRENT_BINARY_DIR}/${pol}.mod)
SET(out ${CMAKE_CURRENT_BINARY_DIR}/${pol}.pp)
ADD_CUSTOM_COMMAND(OUTPUT ${out}
COMMAND ${CHECKMODULE} -M -m ${src} -o ${tmp}
COMMAND ${SEMODULE_PACKAGE} -m ${tmp} -o ${out}
COMMAND ${CMAKE_COMMAND} -E remove ${tmp}
DEPENDS ${src})
ADD_CUSTOM_TARGET(${pol}-pp ALL DEPENDS ${out})
INSTALL(FILES ${out} DESTINATION ${inst_location}/policy/selinux COMPONENT cracklib-password-check)

View File

@@ -5024,7 +5024,7 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
if (unlikely((error= check(thd, check_opt))))
return error;
/* Skip updating frm version if not main handler. */
if (table->file != this)
if (table->file != this || opt_readonly)
return error;
return update_frm_version(table);
}
@@ -5073,7 +5073,7 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
DBUG_ASSERT(result == HA_ADMIN_NOT_IMPLEMENTED ||
ha_table_flags() & HA_CAN_REPAIR);
if (result == HA_ADMIN_OK)
if (result == HA_ADMIN_OK && !opt_readonly)
result= update_frm_version(table);
return result;
}
@@ -6007,7 +6007,7 @@ err:
void st_ha_check_opt::init()
{
flags= sql_flags= 0;
flags= sql_flags= handler_flags= 0;
start_time= my_time(0);
}

View File

@@ -2673,6 +2673,7 @@ typedef struct st_ha_check_opt
st_ha_check_opt() = default; /* Remove gcc warning */
uint flags; /* isam layer flags (e.g. for myisamchk) */
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
uint handler_flags; /* Reserved for handler usage */
time_t start_time; /* When check/repair starts */
KEY_CACHE *key_cache; /* new key cache when changing key cache */
void init();

View File

@@ -3135,6 +3135,53 @@ SQL_SELECT::test_quick_select(THD *thd,
****************************************************************************/
/*
@brief
Create a bitmap of columns for which to perform Range Analysis for EITS
condition selectivity estimates.
@detail
Walk through the bitmap of fields used in the query, and
- pick columns for which EITS data is usable (see is_eits_usable() call)
- do not produce more than MAX_KEY columns. Range Analyzer cannot handle
more than that. If there are more than MAX_KEY eligible columns,
this function should be called multiple times to produce multiple
bitmaps.
@param used_fields Columns used by the query
@param col_no Start from this column
@param out OUT Filled column bitmap
@return
(uint)-1 If there are no more columns for range analysis.
Other Index of the last considered column. Pass this to next call to
this function
*/
uint get_columns_for_pseudo_indexes(const TABLE *table,
const MY_BITMAP *used_fields, int col_no,
MY_BITMAP *out)
{
bitmap_clear_all(out);
int n_bits= 0;
for (; table->field[col_no]; col_no++)
{
if (bitmap_is_set(used_fields, col_no) &&
is_eits_usable(table->field[col_no]))
{
bitmap_set_bit(out, col_no);
if (++n_bits == MAX_KEY)
{
col_no++;
break;
}
}
}
return n_bits? col_no: (uint)-1;
}
/*
Build descriptors of pseudo-indexes over columns to perform range analysis
@@ -3160,22 +3207,11 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
{
Field **field_ptr;
TABLE *table= param->table;
uint parts= 0;
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
Field *field= *field_ptr;
if (bitmap_is_set(used_fields, field->field_index) &&
is_eits_usable(field))
parts++;
}
uint parts= bitmap_bits_set(used_fields);
KEY_PART *key_part;
uint keys= 0;
if (!parts)
return TRUE;
if (!(key_part= (KEY_PART *) alloc_root(param->mem_root,
sizeof(KEY_PART) * parts)))
return TRUE;
@@ -3187,9 +3223,6 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
Field *field= *field_ptr;
if (bitmap_is_set(used_fields, field->field_index))
{
if (!is_eits_usable(field))
continue;
uint16 store_length;
uint16 max_key_part_length= (uint16) table->file->max_key_part_length();
key_part->key= keys;
@@ -3534,8 +3567,6 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
PARAM param;
MEM_ROOT alloc;
SEL_TREE *tree;
double rows;
init_sql_alloc(key_memory_quick_range_select_root, &alloc,
thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
bzero((void*) &param, sizeof(param));
@@ -3545,67 +3576,90 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
param.table= table;
param.remove_false_where_parts= true;
if (create_key_parts_for_pseudo_indexes(&param, used_fields))
goto free_alloc;
param.prev_tables= param.read_tables= 0;
param.current_table= table->map;
param.using_real_indexes= FALSE;
param.real_keynr[0]= 0;
MEM_UNDEFINED(&param.real_keynr, sizeof(param.real_keynr));
param.alloced_sel_args= 0;
param.max_key_parts= 0;
thd->no_errors=1;
tree= cond[0]->get_mm_tree(&param, cond);
if (!tree)
goto free_alloc;
thd->no_errors=1;
table->reginfo.impossible_range= 0;
if (tree->type == SEL_TREE::IMPOSSIBLE)
{
rows= 0;
table->reginfo.impossible_range= 1;
goto free_alloc;
}
else if (tree->type == SEL_TREE::ALWAYS)
{
rows= table_records;
goto free_alloc;
}
else if (tree->type == SEL_TREE::MAYBE)
{
rows= table_records;
goto free_alloc;
}
for (uint idx= 0; idx < param.keys; idx++)
uint used_fields_buff_size= bitmap_buffer_size(table->s->fields);
uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size);
MY_BITMAP cols_for_indexes;
(void) my_bitmap_init(&cols_for_indexes, used_fields_buff, table->s->fields);
bitmap_clear_all(&cols_for_indexes);
uint column_no= 0; // Start looping from the first column.
/*
Try getting selectivity estimates for every field that is used in the
query and has EITS statistics. We do this:
for every usable field col
create a pseudo INDEX(col);
Run the range analyzer (get_mm_tree) for these pseudo-indexes;
Look at produced ranges and get their selectivity estimates;
Note that the range analyzer can process at most MAX_KEY indexes. If
the table has >MAX_KEY eligible columns, we will do several range
analyzer runs.
*/
while (1)
{
SEL_ARG *key= tree->keys[idx];
if (key)
column_no= get_columns_for_pseudo_indexes(table, used_fields, column_no,
&cols_for_indexes);
if (column_no == (uint)-1)
break; /* Couldn't create any pseudo-indexes. This means we're done */
if (create_key_parts_for_pseudo_indexes(&param, &cols_for_indexes))
goto free_alloc;
tree= cond[0]->get_mm_tree(&param, cond);
if (!tree ||
tree->type == SEL_TREE::ALWAYS ||
tree->type == SEL_TREE::MAYBE)
{
Json_writer_object selectivity_for_column(thd);
selectivity_for_column.add("column_name", key->field->field_name);
if (key->type == SEL_ARG::IMPOSSIBLE)
/* Couldn't infer anything. But there could be more fields, so continue */
continue;
}
if (tree->type == SEL_TREE::IMPOSSIBLE)
{
table->reginfo.impossible_range= 1;
goto free_alloc;
}
for (uint idx= 0; idx < param.keys; idx++)
{
SEL_ARG *key= tree->keys[idx];
if (key)
{
rows= 0;
table->reginfo.impossible_range= 1;
selectivity_for_column.add("selectivity_from_histogram", rows);
selectivity_for_column.add("cause", "impossible range");
goto free_alloc;
}
else
{
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
rows= records_in_column_ranges(&param, idx, key);
thd->count_cuted_fields= save_count_cuted_fields;
if (rows != DBL_MAX)
Json_writer_object selectivity_for_column(thd);
selectivity_for_column.add("column_name", key->field->field_name);
if (key->type == SEL_ARG::IMPOSSIBLE)
{
key->field->cond_selectivity= rows/table_records;
selectivity_for_column.add("selectivity_from_histogram",
key->field->cond_selectivity);
table->reginfo.impossible_range= 1;
selectivity_for_column.add("selectivity_from_histogram", 0);
selectivity_for_column.add("cause", "impossible range");
goto free_alloc;
}
else
{
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
double rows= records_in_column_ranges(&param, idx, key);
thd->count_cuted_fields= save_count_cuted_fields;
if (rows != DBL_MAX)
{
key->field->cond_selectivity= rows/table_records;
selectivity_for_column.add("selectivity_from_histogram",
key->field->cond_selectivity);
}
}
}
}

View File

@@ -5707,6 +5707,40 @@ extern "C" void *thd_mdl_context(MYSQL_THD thd)
return &thd->mdl_context;
}
/**
Send check/repair message to the user
@param op one of check or repair
@param msg_type one of info, warning or error
@param print_to_log <> 0 if we should also print the message to error log.
*/
extern "C" void
print_check_msg(THD *thd, const char *db_name, const char *table_name, const char *op,
const char *msg_type, const char *message, my_bool print_to_log)
{
char name[NAME_LEN * 2 + 2];
Protocol *protocol= thd->protocol;
DBUG_ASSERT(strlen(db_name) <= NAME_LEN);
DBUG_ASSERT(strlen(table_name) <= NAME_LEN);
size_t length= size_t(strxnmov(name, sizeof name - 1,
db_name, ".", table_name, NullS) -
name);
protocol->prepare_for_resend();
protocol->store(name, length, system_charset_info);
protocol->store(op, strlen(op), system_charset_info);
protocol->store(msg_type, strlen(msg_type), system_charset_info);
protocol->store(message, strlen(message), system_charset_info);
if (protocol->write())
sql_print_error("Failed on my_net_write, writing to stderr instead: %s: %s\n",
table_name, message);
else if (thd->variables.log_warnings > 2 && print_to_log)
sql_print_error("%s: table '%s' got '%s' during %s",
msg_type, table_name, message, op);
}
/****************************************************************************
Handling of statement states in functions and triggers.

View File

@@ -263,7 +263,10 @@ int update_portion_of_time(THD *thd, TABLE *table,
res= src->save_in_field(table->field[dst_fieldno], true);
if (likely(!res))
{
table->period_prepare_autoinc();
res= table->update_generated_fields();
}
if(likely(!res))
res= table->file->ha_update_row(table->record[1], table->record[0]);

View File

@@ -1233,7 +1233,9 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
/* Execute the query that specifies the derived table by a foreign engine */
res= derived->pushdown_derived->execute();
unit->executed= true;
if (res)
DBUG_RETURN(res);
goto after_exec;
}
if (unit->executed && !derived_is_recursive &&
@@ -1294,6 +1296,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
derived_result, unit, first_select);
}
after_exec:
if (!res && !derived_is_recursive)
{
if (derived_result->flush())

View File

@@ -18,6 +18,7 @@
#include <service_versions.h>
#include <mysql/service_wsrep.h>
#include <mysql/service_thd_mdl.h>
#include <mysql/service_print_check_msg.h>
struct st_service_ref {
const char *name;
@@ -219,6 +220,11 @@ static struct my_print_error_service_st my_print_error_handler=
my_printv_error
};
static struct print_check_msg_service_st print_check_msg_handler=
{
print_check_msg
};
static struct json_service_st json_handler=
{
json_type,
@@ -336,6 +342,7 @@ static struct st_service_ref list_of_services[]=
{ "my_crypt_service", VERSION_my_crypt, &crypt_handler},
{ "my_md5_service", VERSION_my_md5, &my_md5_handler},
{ "my_print_error_service", VERSION_my_print_error, &my_print_error_handler},
{ "print_check_msg_service", VERSION_print_check_msg, &print_check_msg_handler},
{ "my_sha1_service", VERSION_my_sha1, &my_sha1_handler},
{ "my_sha2_service", VERSION_my_sha2, &my_sha2_handler},
{ "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },

View File

@@ -9159,10 +9159,9 @@ int TABLE::update_default_fields(bool ignore_errors)
int TABLE::update_generated_fields()
{
int res= 0;
if (found_next_number_field)
if (next_number_field)
{
next_number_field= found_next_number_field;
res= found_next_number_field->set_default();
res= next_number_field->set_default();
if (likely(!res))
res= file->update_auto_increment();
next_number_field= NULL;
@@ -9177,6 +9176,18 @@ int TABLE::update_generated_fields()
return res;
}
void TABLE::period_prepare_autoinc()
{
if (!found_next_number_field)
return;
/* Don't generate a new value if the autoinc index is WITHOUT OVERLAPS */
DBUG_ASSERT(s->next_number_index != (uint)-1);
if (key_info[s->next_number_index].without_overlaps)
return;
next_number_field= found_next_number_field;
}
int TABLE::period_make_insert(Item *src, Field *dst)
{
THD *thd= in_use;
@@ -9186,7 +9197,10 @@ int TABLE::period_make_insert(Item *src, Field *dst)
int res= src->save_in_field(dst, true);
if (likely(!res))
{
period_prepare_autoinc();
res= update_generated_fields();
}
if (likely(!res) && triggers)
res= triggers->process_triggers(thd, TRG_EVENT_INSERT,

View File

@@ -1840,6 +1840,7 @@ public:
#endif
int update_generated_fields();
void period_prepare_autoinc();
int period_make_insert(Item *src, Field *dst);
int insert_portion_of_time(THD *thd, const vers_select_conds_t &period_conds,
ha_rows *rows_inserted);

View File

@@ -1291,54 +1291,71 @@ btr_read_autoinc(dict_index_t* index)
return autoinc;
}
dict_index_t *dict_table_t::get_index(const dict_col_t &col) const
{
dict_index_t *index= dict_table_get_first_index(this);
while (index && (index->fields[0].col != &col || index->is_corrupted()))
index= dict_table_get_next_index(index);
return index;
}
/** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC,
or fall back to MAX(auto_increment_column).
@param[in] table table containing an AUTO_INCREMENT column
@param[in] col_no index of the AUTO_INCREMENT column
@return the AUTO_INCREMENT value
@retval 0 on error or if no AUTO_INCREMENT value was used yet */
ib_uint64_t
btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
@param table table containing an AUTO_INCREMENT column
@param col_no index of the AUTO_INCREMENT column
@param mysql_version TABLE_SHARE::mysql_version
@param max the maximum value of the AUTO_INCREMENT column
@return the AUTO_INCREMENT value
@retval 0 on error or if no AUTO_INCREMENT value was used yet */
uint64_t btr_read_autoinc_with_fallback(const dict_table_t *table,
unsigned col_no, ulong mysql_version,
uint64_t max)
{
ut_ad(table->persistent_autoinc);
ut_ad(!table->is_temporary());
ut_ad(table->persistent_autoinc);
ut_ad(!table->is_temporary());
dict_index_t* index = dict_table_get_first_index(table);
uint64_t autoinc= 0;
mtr_t mtr;
mtr.start();
if (index == NULL) {
return 0;
}
if (buf_block_t *block=
buf_page_get(page_id_t(table->space_id,
dict_table_get_first_index(table)->page),
table->space->zip_size(), RW_SX_LATCH, &mtr))
{
autoinc= page_get_autoinc(block->page.frame);
mtr_t mtr;
mtr.start();
buf_block_t* block = buf_page_get(
page_id_t(index->table->space_id, index->page),
index->table->space->zip_size(),
RW_S_LATCH, &mtr);
if (autoinc > 0 && autoinc <= max && mysql_version >= 100210);
else if (dict_index_t *index=
table->get_index(*dict_table_get_nth_col(table, col_no)))
{
/* Read MAX(autoinc_col), in case this table had originally been
created before MariaDB 10.2.4 introduced persistent AUTO_INCREMENT
and MariaDB 10.2.10 fixed MDEV-12123, and there could be a garbage
value in the PAGE_ROOT_AUTO_INC field. */
const uint64_t max_autoinc= row_search_max_autoinc(index);
const bool need_adjust{autoinc > max || autoinc < max_autoinc};
ut_ad(max_autoinc <= max);
ib_uint64_t autoinc = block
? page_get_autoinc(block->page.frame) : 0;
const bool retry = block && autoinc == 0
&& !page_is_empty(block->page.frame);
mtr.commit();
if (UNIV_UNLIKELY(need_adjust) && !high_level_read_only && !opt_readonly)
{
sql_print_information("InnoDB: Resetting PAGE_ROOT_AUTO_INC from "
UINT64PF " to " UINT64PF
" on table %`.*s.%`s (created with version %lu)",
autoinc, max_autoinc,
int(table->name.dblen()), table->name.m_name,
table->name.basename(), mysql_version);
autoinc= max_autoinc;
index->set_modified(mtr);
page_set_autoinc(block, max_autoinc, &mtr, true);
}
}
}
if (retry) {
/* This should be an old data file where
PAGE_ROOT_AUTO_INC was initialized to 0.
Fall back to reading MAX(autoinc_col).
There should be an index on it. */
const dict_col_t* autoinc_col
= dict_table_get_nth_col(table, col_no);
while (index && index->fields[0].col != autoinc_col) {
index = dict_table_get_next_index(index);
}
if (index) {
autoinc = row_search_max_autoinc(index);
}
}
return autoinc;
mtr.commit();
return autoinc;
}
/** Write the next available AUTO_INCREMENT value to PAGE_ROOT_AUTO_INC.

View File

@@ -657,47 +657,22 @@ dict_table_t::parse_name<>(char(&)[NAME_LEN + 1], char(&)[NAME_LEN + 1],
/** Acquire MDL shared for the table name.
@tparam trylock whether to use non-blocking operation
@param[in,out] table table object
@param[in,out] thd background thread
@param[out] mdl mdl ticket
@param[in,out] mdl_context MDL context
@param[out] mdl MDL ticket
@param[in] table_op operation to perform when opening
@return table object after locking MDL shared
@retval nullptr if the table is not readable, or if trylock && MDL blocked */
template<bool trylock>
__attribute__((nonnull, warn_unused_result))
dict_table_t*
dict_acquire_mdl_shared(dict_table_t *table,
THD *thd,
MDL_ticket **mdl,
MDL_context *mdl_context, MDL_ticket **mdl,
dict_table_op_t table_op)
{
if (!table || !mdl)
return table;
MDL_context *mdl_context= static_cast<MDL_context*>(thd_mdl_context(thd));
size_t db_len;
dict_table_t *not_found= nullptr;
if (trylock)
{
dict_sys.freeze(SRW_LOCK_CALL);
db_len= dict_get_db_name_len(table->name.m_name);
dict_sys.unfreeze();
}
else
{
ut_ad(dict_sys.frozen_not_locked());
db_len= dict_get_db_name_len(table->name.m_name);
}
if (db_len == 0)
return table; /* InnoDB system tables are not covered by MDL */
if (!mdl_context)
return nullptr;
table_id_t table_id= table->id;
char db_buf[NAME_LEN + 1], db_buf1[NAME_LEN + 1];
char tbl_buf[NAME_LEN + 1], tbl_buf1[NAME_LEN + 1];
size_t tbl_len;
size_t db_len, tbl_len;
bool unaccessible= false;
if (!table->parse_name<!trylock>(db_buf, tbl_buf, &db_len, &tbl_len))
@@ -768,7 +743,6 @@ retry:
if (!table || !table->is_accessible())
{
table= nullptr;
return_without_mdl:
if (trylock)
dict_sys.unfreeze();
@@ -777,7 +751,7 @@ return_without_mdl:
mdl_context->release_lock(*mdl);
*mdl= nullptr;
}
return not_found;
return nullptr;
}
size_t db1_len, tbl1_len;
@@ -814,6 +788,50 @@ return_without_mdl:
goto retry;
}
template dict_table_t* dict_acquire_mdl_shared<false>
(dict_table_t*,MDL_context*,MDL_ticket**,dict_table_op_t);
/** Acquire MDL shared for the table name.
@tparam trylock whether to use non-blocking operation
@param[in,out] table table object
@param[in,out] thd background thread
@param[out] mdl mdl ticket
@param[in] table_op operation to perform when opening
@return table object after locking MDL shared
@retval nullptr if the table is not readable, or if trylock && MDL blocked */
template<bool trylock>
dict_table_t*
dict_acquire_mdl_shared(dict_table_t *table,
THD *thd,
MDL_ticket **mdl,
dict_table_op_t table_op)
{
if (!table || !mdl)
return table;
MDL_context *mdl_context= static_cast<MDL_context*>(thd_mdl_context(thd));
size_t db_len;
if (trylock)
{
dict_sys.freeze(SRW_LOCK_CALL);
db_len= dict_get_db_name_len(table->name.m_name);
dict_sys.unfreeze();
}
else
{
ut_ad(dict_sys.frozen_not_locked());
db_len= dict_get_db_name_len(table->name.m_name);
}
if (db_len == 0)
return table; /* InnoDB system tables are not covered by MDL */
return mdl_context
? dict_acquire_mdl_shared<trylock>(table, mdl_context, mdl, table_op)
: nullptr;
}
template dict_table_t* dict_acquire_mdl_shared<false>
(dict_table_t*,THD*,MDL_ticket**,dict_table_op_t);
template dict_table_t* dict_acquire_mdl_shared<true>
@@ -960,9 +978,6 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line))
{
latch.wr_lock(SRW_LOCK_ARGS(file, line));
latch_ex_wait_start.store(0, std::memory_order_relaxed);
ut_ad(!latch_readers);
ut_ad(!latch_ex);
ut_d(latch_ex= pthread_self());
return;
}
@@ -978,31 +993,21 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line))
ib::warn() << "A long wait (" << waited
<< " seconds) was observed for dict_sys.latch";
latch.wr_lock(SRW_LOCK_ARGS(file, line));
ut_ad(!latch_readers);
ut_ad(!latch_ex);
ut_d(latch_ex= pthread_self());
}
#ifdef UNIV_PFS_RWLOCK
ATTRIBUTE_NOINLINE void dict_sys_t::unlock()
{
ut_ad(latch_ex == pthread_self());
ut_ad(!latch_readers);
ut_d(latch_ex= 0);
latch.wr_unlock();
}
ATTRIBUTE_NOINLINE void dict_sys_t::freeze(const char *file, unsigned line)
{
latch.rd_lock(file, line);
ut_ad(!latch_ex);
ut_d(latch_readers++);
}
ATTRIBUTE_NOINLINE void dict_sys_t::unfreeze()
{
ut_ad(!latch_ex);
ut_ad(latch_readers--);
latch.rd_unlock();
}
#endif /* UNIV_PFS_RWLOCK */

View File

@@ -47,10 +47,13 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include <my_bitmap.h>
#include <mysql/service_thd_alloc.h>
#include <mysql/service_thd_wait.h>
#include <mysql/service_print_check_msg.h>
#include "sql_type_geom.h"
#include "scope.h"
#include "srv0srv.h"
extern my_bool opt_readonly;
// MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system;
// MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[];
@@ -116,6 +119,7 @@ thread_local ha_handler_stats *mariadb_stats= &mariadb_dummy_stats;
#include "snappy-c.h"
#include <limits>
#include <myisamchk.h> // TT_FOR_UPGRADE
#define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X))
@@ -5345,67 +5349,6 @@ test_normalize_table_name_low()
}
}
}
/*********************************************************************
Test ut_format_name(). */
static
void
test_ut_format_name()
/*=================*/
{
char buf[NAME_LEN * 3];
struct {
const char* name;
ulint buf_size;
const char* expected;
} test_data[] = {
{"test/t1", sizeof(buf), "`test`.`t1`"},
{"test/t1", 12, "`test`.`t1`"},
{"test/t1", 11, "`test`.`t1"},
{"test/t1", 10, "`test`.`t"},
{"test/t1", 9, "`test`.`"},
{"test/t1", 8, "`test`."},
{"test/t1", 7, "`test`"},
{"test/t1", 6, "`test"},
{"test/t1", 5, "`tes"},
{"test/t1", 4, "`te"},
{"test/t1", 3, "`t"},
{"test/t1", 2, "`"},
{"test/t1", 1, ""},
{"test/t1", 0, "BUF_NOT_CHANGED"},
{"table", sizeof(buf), "`table`"},
{"ta'le", sizeof(buf), "`ta'le`"},
{"ta\"le", sizeof(buf), "`ta\"le`"},
{"ta`le", sizeof(buf), "`ta``le`"},
};
for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
memcpy(buf, "BUF_NOT_CHANGED", strlen("BUF_NOT_CHANGED") + 1);
char* ret;
ret = ut_format_name(test_data[i].name,
buf,
test_data[i].buf_size);
ut_a(ret == buf);
if (strcmp(buf, test_data[i].expected) == 0) {
ib::info() << "ut_format_name(" << test_data[i].name
<< ", buf, " << test_data[i].buf_size << "),"
" expected " << test_data[i].expected
<< ", OK";
} else {
ib::error() << "ut_format_name(" << test_data[i].name
<< ", buf, " << test_data[i].buf_size << "),"
" expected " << test_data[i].expected
<< ", ERROR: got " << buf;
ut_error;
}
}
}
#endif /* !DBUG_OFF */
/** Match index columns between MySQL and InnoDB.
@@ -5763,9 +5706,9 @@ func_exit:
return ret;
}
/********************************************************************//**
Get the upper limit of the MySQL integral and floating-point type.
@return maximum allowed value for the field */
/** Get the maximum integer value of a numeric column.
@param field column definition
@return maximum allowed integer value */
ulonglong innobase_get_int_col_max_value(const Field *field)
{
ulonglong max_value = 0;
@@ -5830,46 +5773,45 @@ ha_innobase::open().
@param[in,out] table persistent table
@param[in] field the AUTO_INCREMENT column */
static
void
initialize_auto_increment(dict_table_t* table, const Field* field)
static void initialize_auto_increment(dict_table_t *table, const Field& field,
const TABLE_SHARE &s)
{
ut_ad(!table->is_temporary());
ut_ad(!table->is_temporary());
const unsigned col_no= innodb_col_no(&field);
table->autoinc_mutex.wr_lock();
table->persistent_autoinc=
uint16_t(dict_table_get_nth_col_pos(table, col_no, nullptr) + 1) &
dict_index_t::MAX_N_FIELDS;
if (table->autoinc)
/* Already initialized. Our caller checked
table->persistent_autoinc without
autoinc_mutex protection, and there might be multiple
ha_innobase::open() executing concurrently. */;
else if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN)
/* If innodb_force_recovery is set so high that writes
are disabled we force the AUTOINC counter to 0
value effectively disabling writes to the table.
Secondly, we avoid reading the table in case the read
results in failure due to a corrupted table/index.
const unsigned col_no = innodb_col_no(field);
We will not return an error to the client, so that the
tables can be dumped with minimal hassle. If an error
were returned in this case, the first attempt to read
the table would fail and subsequent SELECTs would succeed. */;
else if (table->persistent_autoinc)
{
uint64_t max_value= innobase_get_int_col_max_value(&field);
table->autoinc=
innobase_next_autoinc(btr_read_autoinc_with_fallback(table, col_no,
s.mysql_version,
max_value),
1 /* need */,
1 /* auto_increment_increment */,
0 /* auto_increment_offset */,
max_value);
}
table->autoinc_mutex.wr_lock();
table->persistent_autoinc = static_cast<uint16_t>(
dict_table_get_nth_col_pos(table, col_no, NULL) + 1)
& dict_index_t::MAX_N_FIELDS;
if (table->autoinc) {
/* Already initialized. Our caller checked
table->persistent_autoinc without
autoinc_mutex protection, and there might be multiple
ha_innobase::open() executing concurrently. */
} else if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
/* If the recovery level is set so high that writes
are disabled we force the AUTOINC counter to 0
value effectively disabling writes to the table.
Secondly, we avoid reading the table in case the read
results in failure due to a corrupted table/index.
We will not return an error to the client, so that the
tables can be dumped with minimal hassle. If an error
were returned in this case, the first attempt to read
the table would fail and subsequent SELECTs would succeed. */
} else if (table->persistent_autoinc) {
table->autoinc = innobase_next_autoinc(
btr_read_autoinc_with_fallback(table, col_no),
1 /* need */,
1 /* auto_increment_increment */,
0 /* auto_increment_offset */,
innobase_get_int_col_max_value(field));
}
table->autoinc_mutex.wr_unlock();
table->autoinc_mutex.wr_unlock();
}
/** Open an InnoDB table
@@ -6105,7 +6047,7 @@ ha_innobase::open(const char* name, int, uint)
|| m_prebuilt->table->persistent_autoinc
|| !m_prebuilt->table->is_readable()) {
} else if (const Field* ai = table->found_next_number_field) {
initialize_auto_increment(m_prebuilt->table, ai);
initialize_auto_increment(m_prebuilt->table, *ai, *table->s);
}
/* Set plugin parser for fulltext index */
@@ -13383,6 +13325,49 @@ ha_innobase::discard_or_import_tablespace(
DBUG_RETURN(0);
}
/** Report a DROP TABLE failure due to a FOREIGN KEY constraint.
@param name table name
@param foreign constraint */
ATTRIBUTE_COLD
static void delete_table_cannot_drop_foreign(const table_name_t &name,
const dict_foreign_t &foreign)
{
mysql_mutex_lock(&dict_foreign_err_mutex);
rewind(dict_foreign_err_file);
ut_print_timestamp(dict_foreign_err_file);
fputs(" Cannot drop table ", dict_foreign_err_file);
ut_print_name(dict_foreign_err_file, nullptr, name.m_name);
fputs("\nbecause it is referenced by ", dict_foreign_err_file);
ut_print_name(dict_foreign_err_file, nullptr, foreign.foreign_table_name);
putc('\n', dict_foreign_err_file);
mysql_mutex_unlock(&dict_foreign_err_mutex);
}
/** Check if DROP TABLE would fail due to a FOREIGN KEY constraint.
@param table table to be dropped
@param sqlcom thd_sql_command(current_thd)
@return whether child tables that refer to this table exist */
static bool delete_table_check_foreigns(const dict_table_t &table,
enum_sql_command sqlcom)
{
const bool drop_db{sqlcom == SQLCOM_DROP_DB};
for (const auto foreign : table.referenced_set)
{
/* We should allow dropping a referenced table if creating
that referenced table has failed for some reason. For example
if referenced table is created but it column types that are
referenced do not match. */
if (foreign->foreign_table == &table ||
(drop_db &&
dict_tables_have_same_db(table.name.m_name,
foreign->foreign_table_name_lookup)))
continue;
delete_table_cannot_drop_foreign(table.name, *foreign);
return true;
}
return false;
}
/** DROP TABLE (possibly as part of DROP DATABASE, CREATE/ALTER TABLE)
@param name table name
@@ -13397,8 +13382,8 @@ int ha_innobase::delete_table(const char *name)
DBUG_EXECUTE_IF("test_normalize_table_name_low",
test_normalize_table_name_low(););
DBUG_EXECUTE_IF("test_ut_format_name", test_ut_format_name(););
const enum_sql_command sqlcom= enum_sql_command(thd_sql_command(thd));
trx_t *parent_trx= check_trx_exists(thd);
dict_table_t *table;
@@ -13435,6 +13420,13 @@ int ha_innobase::delete_table(const char *name)
DBUG_RETURN(0);
}
if (parent_trx->check_foreigns &&
delete_table_check_foreigns(*table, sqlcom))
{
dict_sys.unlock();
DBUG_RETURN(HA_ERR_ROW_IS_REFERENCED);
}
table->acquire();
dict_sys.unlock();
@@ -13467,14 +13459,7 @@ int ha_innobase::delete_table(const char *name)
/* FOREIGN KEY constraints cannot exist on partitioned tables. */;
#endif
else
{
dict_sys.freeze(SRW_LOCK_CALL);
for (const dict_foreign_t* f : table->referenced_set)
if (dict_table_t* child= f->foreign_table)
if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS)
break;
dict_sys.unfreeze();
}
err= lock_table_children(table, trx);
}
dict_table_t *table_stats= nullptr, *index_stats= nullptr;
@@ -13484,7 +13469,6 @@ int ha_innobase::delete_table(const char *name)
const bool fts= err == DB_SUCCESS &&
(table->flags2 & (DICT_TF2_FTS_HAS_DOC_ID | DICT_TF2_FTS));
const enum_sql_command sqlcom= enum_sql_command(thd_sql_command(thd));
if (fts)
{
@@ -13642,36 +13626,16 @@ err_exit:
DBUG_RETURN(convert_error_code_to_mysql(err, 0, NULL));
}
if (!table->no_rollback() && trx->check_foreigns)
if (!table->no_rollback())
{
const bool drop_db= sqlcom == SQLCOM_DROP_DB;
for (auto foreign : table->referenced_set)
if (trx->check_foreigns && delete_table_check_foreigns(*table, sqlcom))
{
/* We should allow dropping a referenced table if creating
that referenced table has failed for some reason. For example
if referenced table is created but it column types that are
referenced do not match. */
if (foreign->foreign_table == table ||
(drop_db &&
dict_tables_have_same_db(table->name.m_name,
foreign->foreign_table_name_lookup)))
continue;
mysql_mutex_lock(&dict_foreign_err_mutex);
rewind(dict_foreign_err_file);
ut_print_timestamp(dict_foreign_err_file);
fputs(" Cannot drop table ", dict_foreign_err_file);
ut_print_name(dict_foreign_err_file, trx, table->name.m_name);
fputs("\nbecause it is referenced by ", dict_foreign_err_file);
ut_print_name(dict_foreign_err_file, trx, foreign->foreign_table_name);
putc('\n', dict_foreign_err_file);
mysql_mutex_unlock(&dict_foreign_err_mutex);
err= DB_CANNOT_DROP_CONSTRAINT;
goto err_exit;
}
}
if (!table->no_rollback())
err= trx->drop_table_foreign(table->name);
}
if (err == DB_SUCCESS && table_stats && index_stats)
err= trx->drop_table_statistics(table->name);
@@ -13790,6 +13754,19 @@ int ha_innobase::truncate()
update_thd();
#ifdef UNIV_DEBUG
if (!thd_test_options(m_user_thd, OPTION_NO_FOREIGN_KEY_CHECKS))
{
/* fk_truncate_illegal_if_parent() should have failed in
Sql_cmd_truncate_table::handler_truncate() if foreign_key_checks=ON
and child tables exist. */
dict_sys.freeze(SRW_LOCK_CALL);
for (const auto foreign : m_prebuilt->table->referenced_set)
ut_ad(foreign->foreign_table == m_prebuilt->table);
dict_sys.unfreeze();
}
#endif
if (is_read_only())
DBUG_RETURN(HA_ERR_TABLE_READONLY);
@@ -13872,14 +13849,7 @@ int ha_innobase::truncate()
dict_table_t *table_stats = nullptr, *index_stats = nullptr;
MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr;
dberr_t error= DB_SUCCESS;
dict_sys.freeze(SRW_LOCK_CALL);
for (const dict_foreign_t *f : ib_table->referenced_set)
if (dict_table_t *child= f->foreign_table)
if ((error= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS)
break;
dict_sys.unfreeze();
dberr_t error= lock_table_children(ib_table, trx);
if (error == DB_SUCCESS)
error= lock_table_for_trx(ib_table, trx, LOCK_X);
@@ -14070,16 +14040,7 @@ ha_innobase::rename_table(
/* There is no need to lock any FOREIGN KEY child tables. */
} else if (dict_table_t *table = dict_table_open_on_name(
norm_from, false, DICT_ERR_IGNORE_FK_NOKEY)) {
dict_sys.freeze(SRW_LOCK_CALL);
for (const dict_foreign_t* f : table->referenced_set) {
if (dict_table_t* child = f->foreign_table) {
error = lock_table_for_trx(child, trx, LOCK_X);
if (error != DB_SUCCESS) {
break;
}
}
}
dict_sys.unfreeze();
error = lock_table_children(table, trx);
if (error == DB_SUCCESS) {
error = lock_table_for_trx(table, trx, LOCK_X);
}
@@ -15140,6 +15101,7 @@ ha_innobase::check(
ulint n_rows_in_table = ULINT_UNDEFINED;
bool is_ok = true;
dberr_t ret;
uint handler_flags= check_opt->handler_flags;
DBUG_ENTER("ha_innobase::check");
DBUG_ASSERT(thd == ha_thd());
@@ -15148,6 +15110,27 @@ ha_innobase::check(
ut_a(m_prebuilt->trx == thd_to_trx(thd));
ut_ad(m_prebuilt->trx->mysql_thd == thd);
if (handler_flags || check_for_upgrade(check_opt)) {
/* The file was already checked and fixed as part of open */
print_check_msg(thd, table->s->db.str, table->s->table_name.str,
"check", "note",
(opt_readonly || high_level_read_only
|| !(check_opt->sql_flags & TT_FOR_UPGRADE))
? "Auto_increment will be"
" checked on each open until"
" CHECK TABLE FOR UPGRADE is executed"
: "Auto_increment checked and"
" .frm file version updated", 1);
if (handler_flags && (check_opt->sql_flags & TT_FOR_UPGRADE)) {
/*
No other issues found (as handler_flags was only
set if there as not other problems with the table
than auto_increment).
*/
DBUG_RETURN(HA_ADMIN_OK);
}
}
if (m_prebuilt->mysql_template == NULL) {
/* Build the template; we will use a dummy template
in index scans done in checking */
@@ -15351,6 +15334,35 @@ func_exit:
DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
}
/**
Check if we there is a problem with the InnoDB table.
@param check_opt check options
@retval HA_ADMIN_OK if Table is ok
@retval HA_ADMIN_NEEDS_ALTER User should run ALTER TABLE FOR UPGRADE
@retval HA_ADMIN_NEEDS_CHECK User should run CHECK TABLE FOR UPGRADE
@retval HA_ADMIN_FAILED if InnoDB is in read-only mode */
int ha_innobase::check_for_upgrade(HA_CHECK_OPT *check_opt)
{
/*
Check if there is a possibility that the auto increment value
stored in PAGE_ROOT_AUTO_INC could be corrupt.
*/
if (table->s->mysql_version >= 100210);
else if (const Field *auto_increment= table->found_next_number_field)
{
uint col_no= innodb_col_no(auto_increment);
const dict_col_t *autoinc_col=
dict_table_get_nth_col(m_prebuilt->table, col_no);
if (m_prebuilt->table->get_index(*autoinc_col))
{
check_opt->handler_flags= 1;
return (high_level_read_only && !opt_readonly)
? HA_ADMIN_FAILED : HA_ADMIN_NEEDS_CHECK;
}
}
return HA_ADMIN_OK;
}
/*******************************************************************//**
Gets the foreign key create info for a table stored in InnoDB.
@return own: character string in the form which can be inserted to the
@@ -17535,6 +17547,7 @@ innodb_make_page_dirty(THD*, st_mysql_sys_var*, void*, const void* save)
{
mtr_t mtr;
uint space_id = *static_cast<const uint*>(save);
srv_fil_make_page_dirty_debug= space_id;
mysql_mutex_unlock(&LOCK_global_system_variables);
fil_space_t* space = fil_space_t::get(space_id);
@@ -18261,13 +18274,15 @@ buf_flush_list_now_set(THD*, st_mysql_sys_var*, void*, const void* save)
return;
const uint s= srv_fil_make_page_dirty_debug;
mysql_mutex_unlock(&LOCK_global_system_variables);
if (s)
buf_flush_sync();
else
if (s == 0 || srv_is_undo_tablespace(s))
{
while (buf_flush_list_space(fil_system.sys_space, nullptr));
fil_space_t *space= fil_system.sys_space;
if (s) { space= fil_space_get(s); }
while (buf_flush_list_space(space, nullptr));
os_aio_wait_until_no_pending_writes(true);
}
else
buf_flush_sync();
mysql_mutex_lock(&LOCK_global_system_variables);
}

View File

@@ -209,6 +209,7 @@ public:
int rename_table(const char* from, const char* to) override;
inline int defragment_table();
int check(THD* thd, HA_CHECK_OPT* check_opt) override;
int check_for_upgrade(HA_CHECK_OPT* check_opt) override;
inline void reload_statistics();
@@ -909,6 +910,12 @@ unsigned
innodb_col_no(const Field* field)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Get the maximum integer value of a numeric column.
@param field column definition
@return maximum allowed integer value */
ulonglong innobase_get_int_col_max_value(const Field *field)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/********************************************************************//**
Helper function to push frm mismatch error to error log and
if needed to sql-layer. */

View File

@@ -1458,11 +1458,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
}
};
/********************************************************************//**
Get the upper limit of the MySQL integral and floating-point type.
@return maximum allowed value for the field */
ulonglong innobase_get_int_col_max_value(const Field *field);
/** Determine if fulltext indexes exist in a given table.
@param table MySQL table
@return number of fulltext indexes */
@@ -9865,13 +9860,7 @@ commit_set_autoinc(
const dict_col_t* autoinc_col
= dict_table_get_nth_col(ctx->old_table,
innodb_col_no(ai));
dict_index_t* index
= dict_table_get_first_index(ctx->old_table);
while (index != NULL
&& index->fields[0].col != autoinc_col) {
index = dict_table_get_next_index(index);
}
auto index = ctx->old_table->get_index(*autoinc_col);
ut_ad(index);
ib_uint64_t max_in_table = index
@@ -11224,16 +11213,7 @@ ha_innobase::commit_inplace_alter_table(
fts_optimize_remove_table(ctx->old_table);
}
dict_sys.freeze(SRW_LOCK_CALL);
for (auto f : ctx->old_table->referenced_set) {
if (dict_table_t* child = f->foreign_table) {
error = lock_table_for_trx(child, trx, LOCK_X);
if (error != DB_SUCCESS) {
break;
}
}
}
dict_sys.unfreeze();
error = lock_table_children(ctx->old_table, trx);
if (ctx->new_table->fts) {
ut_ad(!ctx->new_table->fts->add_wq);

View File

@@ -189,13 +189,16 @@ btr_read_autoinc(dict_index_t* index)
/** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC,
or fall back to MAX(auto_increment_column).
@param[in] table table containing an AUTO_INCREMENT column
@param[in] col_no index of the AUTO_INCREMENT column
@return the AUTO_INCREMENT value
@retval 0 on error or if no AUTO_INCREMENT value was used yet */
ib_uint64_t
btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
MY_ATTRIBUTE((nonnull, warn_unused_result));
@param table table containing an AUTO_INCREMENT column
@param col_no index of the AUTO_INCREMENT column
@param mysql_version TABLE_SHARE::mysql_version
@param max the maximum value of the AUTO_INCREMENT column
@return the AUTO_INCREMENT value
@retval 0 on error or if no AUTO_INCREMENT value was used yet */
uint64_t btr_read_autoinc_with_fallback(const dict_table_t *table,
unsigned col_no, ulong mysql_version,
uint64_t max)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Write the next available AUTO_INCREMENT value to PAGE_ROOT_AUTO_INC.
@param[in,out] index clustered index

View File

@@ -35,6 +35,7 @@ Created 1/8/1996 Heikki Tuuri
#include <my_sys.h>
#include <deque>
class MDL_context;
class MDL_ticket;
/** the first table or index ID for other than hard-coded system tables */
@@ -139,6 +140,21 @@ dict_acquire_mdl_shared(dict_table_t *table,
MDL_ticket **mdl,
dict_table_op_t table_op= DICT_TABLE_OP_NORMAL);
/** Acquire MDL shared for the table name.
@tparam trylock whether to use non-blocking operation
@param[in,out] table table object
@param[in,out] mdl_context MDL context
@param[out] mdl MDL ticket
@param[in] table_op operation to perform when opening
@return table object after locking MDL shared
@retval nullptr if the table is not readable, or if trylock && MDL blocked */
template<bool trylock>
__attribute__((nonnull, warn_unused_result))
dict_table_t*
dict_acquire_mdl_shared(dict_table_t *table,
MDL_context *mdl_context, MDL_ticket **mdl,
dict_table_op_t table_op);
/** Look up a table by numeric identifier.
@param[in] table_id table identifier
@param[in] dict_locked data dictionary locked
@@ -1314,13 +1330,7 @@ class dict_sys_t
std::atomic<ulonglong> latch_ex_wait_start;
/** the rw-latch protecting the data dictionary cache */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch;
#ifdef UNIV_DEBUG
/** whether latch is being held in exclusive mode (by any thread) */
Atomic_relaxed<pthread_t> latch_ex;
/** number of S-latch holders */
Atomic_counter<uint32_t> latch_readers;
#endif
alignas(CPU_LEVEL1_DCACHE_LINESIZE) IF_DBUG(srw_lock_debug,srw_lock) latch;
public:
/** Indexes of SYS_TABLE[] */
enum
@@ -1488,15 +1498,12 @@ public:
}
#ifdef UNIV_DEBUG
/** @return whether any thread (not necessarily the current thread)
is holding the latch; that is, this check may return false
positives */
bool frozen() const { return latch_readers || latch_ex; }
/** @return whether any thread (not necessarily the current thread)
is holding a shared latch */
bool frozen_not_locked() const { return latch_readers; }
/** @return whether the current thread is holding the latch */
bool frozen() const { return latch.have_any(); }
/** @return whether the current thread is holding a shared latch */
bool frozen_not_locked() const { return latch.have_rd(); }
/** @return whether the current thread holds the exclusive latch */
bool locked() const { return latch_ex == pthread_self(); }
bool locked() const { return latch.have_wr(); }
#endif
private:
/** Acquire the exclusive latch */
@@ -1511,13 +1518,7 @@ public:
/** Exclusively lock the dictionary cache. */
void lock(SRW_LOCK_ARGS(const char *file, unsigned line))
{
if (latch.wr_lock_try())
{
ut_ad(!latch_readers);
ut_ad(!latch_ex);
ut_d(latch_ex= pthread_self());
}
else
if (!latch.wr_lock_try())
lock_wait(SRW_LOCK_ARGS(file, line));
}
@@ -1530,27 +1531,11 @@ public:
ATTRIBUTE_NOINLINE void unfreeze();
#else
/** Unlock the data dictionary cache. */
void unlock()
{
ut_ad(latch_ex == pthread_self());
ut_ad(!latch_readers);
ut_d(latch_ex= 0);
latch.wr_unlock();
}
void unlock() { latch.wr_unlock(); }
/** Acquire a shared lock on the dictionary cache. */
void freeze()
{
latch.rd_lock();
ut_ad(!latch_ex);
ut_d(latch_readers++);
}
void freeze() { latch.rd_lock(); }
/** Release a shared lock on the dictionary cache. */
void unfreeze()
{
ut_ad(!latch_ex);
ut_ad(latch_readers--);
latch.rd_unlock();
}
void unfreeze() { latch.rd_unlock(); }
#endif
/** Estimate the used memory occupied by the data dictionary

View File

@@ -2448,6 +2448,9 @@ public:
/** @return number of unique columns in FTS_DOC_ID index */
unsigned fts_n_uniq() const { return versioned() ? 2 : 1; }
/** @return the index for that starts with a specific column */
dict_index_t *get_index(const dict_col_t &col) const;
/** Create metadata.
@param name table name
@param space tablespace

View File

@@ -347,7 +347,6 @@ struct fil_space_t final
~fil_space_t()
{
ut_ad(!latch_owner);
ut_ad(!latch_count);
latch.destroy();
}
@@ -411,9 +410,9 @@ private:
/** The reference count */
static constexpr uint32_t PENDING= ~(STOPPING | CLOSING | NEEDS_FSYNC);
/** latch protecting all page allocation bitmap pages */
srw_lock latch;
IF_DBUG(srw_lock_debug, srw_lock) latch;
/** the thread that holds the exclusive latch, or 0 */
pthread_t latch_owner;
ut_d(Atomic_relaxed<uint32_t> latch_count;)
public:
/** MariaDB encryption data */
fil_space_crypt_t *crypt_data;
@@ -1004,40 +1003,32 @@ public:
bool recheck, bool encrypt);
#ifdef UNIV_DEBUG
bool is_latched() const { return latch_count != 0; }
bool is_latched() const { return latch.have_any(); }
#endif
bool is_owner() const { return latch_owner == pthread_self(); }
bool is_owner() const
{
const bool owner{latch_owner == pthread_self()};
ut_ad(owner == latch.have_wr());
return owner;
}
/** Acquire the allocation latch in exclusive mode */
void x_lock()
{
latch.wr_lock(SRW_LOCK_CALL);
ut_ad(!latch_owner);
latch_owner= pthread_self();
ut_ad(!latch_count.fetch_add(1));
}
/** Release the allocation latch from exclusive mode */
void x_unlock()
{
ut_ad(latch_count.fetch_sub(1) == 1);
ut_ad(latch_owner == pthread_self());
latch_owner= 0;
latch.wr_unlock();
}
/** Acquire the allocation latch in shared mode */
void s_lock()
{
ut_ad(!is_owner());
latch.rd_lock(SRW_LOCK_CALL);
ut_ad(!latch_owner);
ut_d(latch_count.fetch_add(1));
}
void s_lock() { latch.rd_lock(SRW_LOCK_CALL); }
/** Release the allocation latch from shared mode */
void s_unlock()
{
ut_ad(latch_count.fetch_sub(1));
ut_ad(!latch_owner);
latch.rd_unlock();
}
void s_unlock() { latch.rd_unlock(); }
typedef span<const char> name_type;

View File

@@ -438,6 +438,13 @@ dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode,
bool no_wait= false)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Lock the child tables of a table.
@param table parent table
@param trx transaction
@return error code */
dberr_t lock_table_children(dict_table_t *table, trx_t *trx)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Exclusively lock the data dictionary tables.
@param trx dictionary transaction
@return error code
@@ -724,13 +731,8 @@ private:
bool m_initialised;
/** mutex proteting the locks */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_spin_lock latch;
#ifdef UNIV_DEBUG
/** The owner of exclusive latch (0 if none); protected by latch */
std::atomic<pthread_t> writer{0};
/** Number of shared latches */
std::atomic<ulint> readers{0};
#endif
alignas(CPU_LEVEL1_DCACHE_LINESIZE)
IF_DBUG(srw_lock_debug,srw_spin_lock) latch;
#ifdef SUX_LOCK_GENERIC
protected:
/** mutex for hash_latch::wait() */
@@ -789,71 +791,35 @@ public:
void wr_lock()
{
mysql_mutex_assert_not_owner(&wait_mutex);
ut_ad(!is_writer());
latch.wr_lock();
ut_ad(!writer.exchange(pthread_self(),
std::memory_order_relaxed));
}
/** Release exclusive lock_sys.latch */
void wr_unlock()
{
ut_ad(writer.exchange(0, std::memory_order_relaxed) ==
pthread_self());
latch.wr_unlock();
}
void wr_unlock() { latch.wr_unlock(); }
/** Acquire shared lock_sys.latch */
void rd_lock()
{
mysql_mutex_assert_not_owner(&wait_mutex);
ut_ad(!is_writer());
latch.rd_lock();
ut_ad(!writer.load(std::memory_order_relaxed));
ut_d(readers.fetch_add(1, std::memory_order_relaxed));
}
/** Release shared lock_sys.latch */
void rd_unlock()
{
ut_ad(!is_writer());
ut_ad(readers.fetch_sub(1, std::memory_order_relaxed));
latch.rd_unlock();
}
void rd_unlock() { latch.rd_unlock(); }
#endif
/** Try to acquire exclusive lock_sys.latch
@return whether the latch was acquired */
bool wr_lock_try()
{
ut_ad(!is_writer());
if (!latch.wr_lock_try()) return false;
ut_ad(!writer.exchange(pthread_self(),
std::memory_order_relaxed));
return true;
}
bool wr_lock_try() { return latch.wr_lock_try(); }
/** Try to acquire shared lock_sys.latch
@return whether the latch was acquired */
bool rd_lock_try()
{
ut_ad(!is_writer());
if (!latch.rd_lock_try()) return false;
ut_ad(!writer.load(std::memory_order_relaxed));
ut_d(readers.fetch_add(1, std::memory_order_relaxed));
return true;
}
bool rd_lock_try() { return latch.rd_lock_try(); }
/** Assert that wr_lock() has been invoked by this thread */
void assert_locked() const { ut_ad(is_writer()); }
void assert_locked() const { ut_ad(latch.have_wr()); }
/** Assert that wr_lock() has not been invoked by this thread */
void assert_unlocked() const { ut_ad(!is_writer()); }
void assert_unlocked() const { ut_ad(!latch.have_wr()); }
#ifdef UNIV_DEBUG
/** @return whether the current thread is the lock_sys.latch writer */
bool is_writer() const
{
# ifdef SUX_LOCK_GENERIC
return writer.load(std::memory_order_relaxed) == pthread_self();
# else
return writer.load(std::memory_order_relaxed) == pthread_self() ||
(xtest() && !latch.is_locked_or_waiting());
# endif
}
bool is_writer() const { return latch.have_wr(); }
/** @return whether the current thread is holding lock_sys.latch */
bool is_holder() const { return latch.have_any(); }
/** Assert that a lock shard is exclusively latched (by some thread) */
void assert_locked(const lock_t &lock) const;
/** Assert that a table lock shard is exclusively latched by this thread */
@@ -965,14 +931,14 @@ extern lock_sys_t lock_sys;
/** @return the index of an array element */
inline ulint lock_sys_t::hash_table::calc_hash(ulint fold) const
{
ut_ad(lock_sys.is_writer() || lock_sys.readers);
ut_ad(lock_sys.is_holder());
return calc_hash(fold, n_cells);
}
/** Get a hash table cell. */
inline hash_cell_t *lock_sys_t::hash_table::cell_get(ulint fold) const
{
ut_ad(lock_sys.is_writer() || lock_sys.readers);
ut_ad(lock_sys.is_holder());
return &array[calc_hash(fold)];
}

View File

@@ -153,7 +153,7 @@ template<bool spinloop> class srw_lock_impl;
/** Slim shared-update-exclusive lock with no recursion */
template<bool spinloop>
class ssux_lock_impl final
class ssux_lock_impl
{
#ifdef UNIV_PFS_RWLOCK
friend class ssux_lock;
@@ -550,3 +550,51 @@ typedef srw_lock_impl<false> srw_lock;
typedef srw_lock_impl<true> srw_spin_lock;
#endif
#ifdef UNIV_DEBUG
# include <unordered_set>
class srw_lock_debug : private srw_lock
{
/** The owner of the exclusive lock (0 if none) */
std::atomic<pthread_t> writer;
/** Protects readers */
mutable srw_mutex readers_lock;
/** Threads that hold the lock in shared mode */
std::atomic<std::unordered_multiset<pthread_t>*> readers;
/** Register a read lock. */
void readers_register();
public:
void SRW_LOCK_INIT(mysql_pfs_key_t key);
void destroy();
#ifndef SUX_LOCK_GENERIC
/** @return whether any lock may be held by any thread */
bool is_locked_or_waiting() const noexcept
{ return srw_lock::is_locked_or_waiting(); }
/** @return whether an exclusive lock may be held by any thread */
bool is_write_locked() const noexcept { return srw_lock::is_write_locked(); }
#endif
/** Acquire an exclusive lock */
void wr_lock(SRW_LOCK_ARGS(const char *file, unsigned line));
/** @return whether an exclusive lock was acquired */
bool wr_lock_try();
/** Release after wr_lock() */
void wr_unlock();
/** Acquire a shared lock */
void rd_lock(SRW_LOCK_ARGS(const char *file, unsigned line));
/** @return whether a shared lock was acquired */
bool rd_lock_try();
/** Release after rd_lock() */
void rd_unlock();
/** @return whether this thread is between rd_lock() and rd_unlock() */
bool have_rd() const noexcept;
/** @return whether this thread is between wr_lock() and wr_unlock() */
bool have_wr() const noexcept;
/** @return whether this thread is holding rd_lock() or wr_lock() */
bool have_any() const noexcept;
};
#endif

View File

@@ -59,7 +59,7 @@ struct alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t
/** tablespace containing the rollback segment; constant after init() */
fil_space_t *space;
/** latch protecting everything except page_no, space */
srw_spin_lock latch;
IF_DBUG(srw_lock_debug,srw_spin_lock) latch;
/** rollback segment header page number; constant after init() */
uint32_t page_no;
/** length of the TRX_RSEG_HISTORY list (number of transactions) */

View File

@@ -242,20 +242,6 @@ ut_print_name(
FILE* ef, /*!< in: stream */
const trx_t* trx, /*!< in: transaction */
const char* name); /*!< in: table name to print */
/** Format a table name, quoted as an SQL identifier.
If the name contains a slash '/', the result will contain two
identifiers separated by a period (.), as in SQL
database_name.table_name.
@see table_name_t
@param[in] name table or index name
@param[out] formatted formatted result, will be NUL-terminated
@param[in] formatted_size size of the buffer in bytes
@return pointer to 'formatted' */
char*
ut_format_name(
const char* name,
char* formatted,
ulint formatted_size);
/**********************************************************************//**
Catenate files. */

View File

@@ -47,6 +47,7 @@ Created 5/7/1996 Heikki Tuuri
#include "que0que.h"
#include "scope.h"
#include <debug_sync.h>
#include <mysql/service_thd_mdl.h>
#include <set>
@@ -173,7 +174,7 @@ void lock_sys_t::assert_locked(const dict_table_t &table) const
ut_ad(!table.is_temporary());
if (is_writer())
return;
ut_ad(readers);
ut_ad(latch.have_rd());
ut_ad(table.lock_mutex_is_owner());
}
@@ -182,7 +183,7 @@ void lock_sys_t::hash_table::assert_locked(const page_id_t id) const
{
if (lock_sys.is_writer())
return;
ut_ad(lock_sys.readers);
ut_ad(lock_sys.is_holder());
ut_ad(latch(cell_get(id.fold()))->is_locked());
}
@@ -191,7 +192,7 @@ void lock_sys_t::assert_locked(const hash_cell_t &cell) const
{
if (is_writer())
return;
ut_ad(lock_sys.readers);
ut_ad(lock_sys.is_holder());
ut_ad(hash_table::latch(const_cast<hash_cell_t*>(&cell))->is_locked());
}
#endif
@@ -426,13 +427,10 @@ void lock_sys_t::wr_lock(const char *file, unsigned line)
{
mysql_mutex_assert_not_owner(&wait_mutex);
latch.wr_lock(file, line);
ut_ad(!writer.exchange(pthread_self(), std::memory_order_relaxed));
}
/** Release exclusive lock_sys.latch */
void lock_sys_t::wr_unlock()
{
ut_ad(writer.exchange(0, std::memory_order_relaxed) ==
pthread_self());
latch.wr_unlock();
}
@@ -441,15 +439,11 @@ void lock_sys_t::rd_lock(const char *file, unsigned line)
{
mysql_mutex_assert_not_owner(&wait_mutex);
latch.rd_lock(file, line);
ut_ad(!writer.load(std::memory_order_relaxed));
ut_d(readers.fetch_add(1, std::memory_order_relaxed));
}
/** Release shared lock_sys.latch */
void lock_sys_t::rd_unlock()
{
ut_ad(!writer.load(std::memory_order_relaxed));
ut_ad(readers.fetch_sub(1, std::memory_order_relaxed));
latch.rd_unlock();
}
#endif
@@ -3940,6 +3934,8 @@ static void lock_table_dequeue(lock_t *in_lock, bool owns_wait_mutex)
dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode,
bool no_wait)
{
ut_ad(!dict_sys.frozen());
mem_heap_t *heap= mem_heap_create(512);
sel_node_t *node= sel_node_create(heap);
que_thr_t *thr= pars_complete_graph_for_exec(node, trx, heap, nullptr);
@@ -3976,6 +3972,67 @@ run_again:
return err;
}
/** Lock the child tables of a table.
@param table parent table
@param trx transaction
@return error code */
dberr_t lock_table_children(dict_table_t *table, trx_t *trx)
{
MDL_context *mdl_context=
static_cast<MDL_context*>(thd_mdl_context(trx->mysql_thd));
ut_ad(mdl_context);
struct table_mdl{dict_table_t* table; MDL_ticket *mdl;};
std::vector<table_mdl> children;
children.emplace_back(table_mdl{table, nullptr});
dberr_t err= DB_SUCCESS;
dict_sys.freeze(SRW_LOCK_CALL);
rescan:
for (auto f : table->referenced_set)
if (dict_table_t *child= f->foreign_table)
{
if (std::find_if(children.begin(), children.end(),
[&](const table_mdl &c){ return c.table == child; }) !=
children.end())
continue; /* We already acquired MDL on this child table. */
MDL_ticket *mdl= nullptr;
child->acquire();
child= dict_acquire_mdl_shared<false>(child, mdl_context, &mdl,
DICT_TABLE_OP_NORMAL);
if (child)
{
if (!mdl)
child->release();
children.emplace_back(table_mdl{child, mdl});
goto rescan;
}
err= DB_LOCK_WAIT_TIMEOUT;
break;
}
dict_sys.unfreeze();
if (err == DB_SUCCESS)
for (const table_mdl &child : children)
if (child.mdl)
if ((err= lock_table_for_trx(child.table, trx, LOCK_X)) != DB_SUCCESS)
break;
dict_sys.freeze(SRW_LOCK_CALL);
for (table_mdl &child : children)
{
if (child.mdl)
{
child.table->release();
mdl_context->release_lock(child.mdl);
}
}
dict_sys.unfreeze();
return err;
}
/** Exclusively lock the data dictionary tables.
@param trx dictionary transaction
@return error code

View File

@@ -175,7 +175,9 @@ void log_file_t::write(os_offset_t offset, span<const byte> buf) noexcept
ut_ad(is_opened());
if (dberr_t err= os_file_write_func(IORequestWrite, "ib_logfile0", m_file,
buf.data(), offset, buf.size()))
ib::fatal() << "write(\"ib_logfile0\") returned " << err;
ib::fatal() << "write(\"ib_logfile0\") returned " << err
<< ". Operating system error number "
<< IF_WIN(GetLastError(), errno) << ".";
}
#ifdef HAVE_PMEM

View File

@@ -4120,9 +4120,10 @@ static bool recv_scan_log(bool last_phase)
const lsn_t end{recv_sys.file_checkpoint};
ut_ad(!end || end == recv_sys.lsn);
bool corrupt_fs= recv_sys.is_corrupt_fs();
mysql_mutex_unlock(&recv_sys.mutex);
if (!end)
if (!end && !corrupt_fs)
{
recv_sys.set_corrupt_log();
sql_print_error("InnoDB: Missing FILE_CHECKPOINT(" LSN_PF
@@ -4602,6 +4603,9 @@ read_only_recovery:
LSN_PF, recv_sys.lsn);
goto err_exit;
}
if (recv_sys.is_corrupt_fs()) {
goto err_exit;
}
ut_ad(recv_sys.file_checkpoint);
if (rewind) {
recv_sys.lsn = log_sys.next_checkpoint_lsn;
@@ -4640,9 +4644,9 @@ read_only_recovery:
do {
rescan = recv_scan_log(false);
ut_ad(!recv_sys.is_corrupt_fs());
if (recv_sys.is_corrupt_log()) {
if (recv_sys.is_corrupt_log() ||
recv_sys.is_corrupt_fs()) {
goto err_exit;
}

View File

@@ -513,10 +513,8 @@ void mtr_t::rollback_to_savepoint(ulint begin, ulint end)
/** Set create_lsn. */
inline void fil_space_t::set_create_lsn(lsn_t lsn)
{
#ifndef SUX_LOCK_GENERIC
/* Concurrent log_checkpoint_low() must be impossible. */
ut_ad(latch.is_write_locked());
#endif
ut_ad(latch.have_wr());
create_lsn= lsn;
}

View File

@@ -45,6 +45,8 @@ Created 2012-02-08 by Sunny Bains.
#include "lzo/lzo1x.h"
#include "snappy-c.h"
#include "log.h"
#include "table.h"
#include "ha_innodb.h"
#include "scope.h"
@@ -4228,6 +4230,37 @@ fil_tablespace_iterate(
return(err);
}
static void row_import_autoinc(dict_table_t *table, row_prebuilt_t *prebuilt,
uint64_t autoinc)
{
if (!table->persistent_autoinc)
{
ut_ad(!autoinc);
return;
}
if (autoinc)
{
btr_write_autoinc(dict_table_get_first_index(table), autoinc - 1);
autoinc_set:
table->autoinc= autoinc;
sql_print_information("InnoDB: %`.*s.%`s autoinc value set to " UINT64PF,
int(table->name.dblen()), table->name.m_name,
table->name.basename(), autoinc);
}
else if (TABLE *t= prebuilt->m_mysql_table)
{
if (const Field *ai= t->found_next_number_field)
{
autoinc= 1 +
btr_read_autoinc_with_fallback(table, innodb_col_no(ai),
t->s->mysql_version,
innobase_get_int_col_max_value(ai));
goto autoinc_set;
}
}
}
/*****************************************************************//**
Imports a tablespace. The space id in the .ibd file must match the space id
of the table in the data dictionary.
@@ -4565,14 +4598,8 @@ row_import_for_mysql(
table->flags2 &= ~DICT_TF2_DISCARDED & ((1U << DICT_TF2_BITS) - 1);
/* Set autoinc value read from .cfg file, if one was specified.
Otherwise, keep the PAGE_ROOT_AUTO_INC as is. */
if (autoinc) {
ib::info() << table->name << " autoinc value set to "
<< autoinc;
table->autoinc = autoinc--;
btr_write_autoinc(dict_table_get_first_index(table), autoinc);
}
Otherwise, read the PAGE_ROOT_AUTO_INC and set it to table autoinc. */
row_import_autoinc(table, prebuilt, autoinc);
return row_import_cleanup(prebuilt, err);
}

View File

@@ -548,3 +548,120 @@ template void ssux_lock_impl<false>::rd_unlock();
template void ssux_lock_impl<false>::u_unlock();
template void ssux_lock_impl<false>::wr_unlock();
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_DEBUG
void srw_lock_debug::SRW_LOCK_INIT(mysql_pfs_key_t key)
{
srw_lock::SRW_LOCK_INIT(key);
readers_lock.init();
ut_ad(!readers.load(std::memory_order_relaxed));
ut_ad(!have_any());
}
void srw_lock_debug::destroy()
{
ut_ad(!writer);
if (auto r= readers.load(std::memory_order_relaxed))
{
readers.store(0, std::memory_order_relaxed);
ut_ad(r->empty());
delete r;
}
srw_lock::destroy();
}
bool srw_lock_debug::wr_lock_try()
{
ut_ad(!have_any());
if (!srw_lock::wr_lock_try())
return false;
ut_ad(!writer);
writer.store(pthread_self(), std::memory_order_relaxed);
return true;
}
void srw_lock_debug::wr_lock(SRW_LOCK_ARGS(const char *file, unsigned line))
{
ut_ad(!have_any());
srw_lock::wr_lock(SRW_LOCK_ARGS(file, line));
ut_ad(!writer);
writer.store(pthread_self(), std::memory_order_relaxed);
}
void srw_lock_debug::wr_unlock()
{
ut_ad(have_wr());
writer.store(0, std::memory_order_relaxed);
srw_lock::wr_unlock();
}
void srw_lock_debug::readers_register()
{
readers_lock.wr_lock();
auto r= readers.load(std::memory_order_relaxed);
if (!r)
{
r= new std::unordered_multiset<pthread_t>();
readers.store(r, std::memory_order_relaxed);
}
r->emplace(pthread_self());
readers_lock.wr_unlock();
}
bool srw_lock_debug::rd_lock_try()
{
ut_ad(!have_any());
if (!srw_lock::rd_lock_try())
return false;
readers_register();
return true;
}
void srw_lock_debug::rd_lock(SRW_LOCK_ARGS(const char *file, unsigned line))
{
ut_ad(!have_any());
srw_lock::rd_lock(SRW_LOCK_ARGS(file, line));
readers_register();
}
void srw_lock_debug::rd_unlock()
{
const pthread_t self= pthread_self();
ut_ad(writer != self);
readers_lock.wr_lock();
auto r= readers.load(std::memory_order_relaxed);
ut_ad(r);
auto i= r->find(self);
ut_ad(i != r->end());
r->erase(i);
readers_lock.wr_unlock();
srw_lock::rd_unlock();
}
bool srw_lock_debug::have_rd() const noexcept
{
if (auto r= readers.load(std::memory_order_relaxed))
{
readers_lock.wr_lock();
bool found= r->find(pthread_self()) != r->end();
readers_lock.wr_unlock();
ut_ad(!found || is_locked());
return found;
}
return false;
}
bool srw_lock_debug::have_wr() const noexcept
{
if (writer != pthread_self())
return false;
ut_ad(is_write_locked());
return true;
}
bool srw_lock_debug::have_any() const noexcept
{
return have_wr() || have_rd();
}
#endif

View File

@@ -396,9 +396,7 @@ static void trx_purge_free_segment(buf_block_t *rseg_hdr, buf_block_t *block,
void purge_sys_t::rseg_enable(trx_rseg_t &rseg)
{
ut_ad(this == &purge_sys);
#ifndef SUX_LOCK_GENERIC
ut_ad(rseg.latch.is_write_locked());
#endif
ut_ad(rseg.latch.have_wr());
uint8_t skipped= skipped_rseg;
ut_ad(skipped < TRX_SYS_N_RSEGS);
if (&rseg == &trx_sys.rseg_array[skipped])
@@ -874,9 +872,7 @@ void purge_sys_t::rseg_get_next_history_log()
{
fil_addr_t prev_log_addr;
#ifndef SUX_LOCK_GENERIC
ut_ad(rseg->latch.is_write_locked());
#endif
ut_ad(rseg->latch.have_wr());
ut_a(rseg->last_page_no != FIL_NULL);
tail.trx_no= rseg->last_trx_no() + 1;
@@ -992,9 +988,7 @@ inline trx_purge_rec_t purge_sys_t::get_next_rec(roll_ptr_t roll_ptr)
{
ut_ad(next_stored);
ut_ad(tail.trx_no < low_limit_no());
#ifndef SUX_LOCK_GENERIC
ut_ad(rseg->latch.is_write_locked());
#endif
ut_ad(rseg->latch.have_wr());
if (!offset)
{

View File

@@ -258,47 +258,6 @@ ut_print_name(
}
}
/** Format a table name, quoted as an SQL identifier.
If the name contains a slash '/', the result will contain two
identifiers separated by a period (.), as in SQL
database_name.table_name.
@see table_name_t
@param[in] name table or index name
@param[out] formatted formatted result, will be NUL-terminated
@param[in] formatted_size size of the buffer in bytes
@return pointer to 'formatted' */
char*
ut_format_name(
const char* name,
char* formatted,
ulint formatted_size)
{
switch (formatted_size) {
case 1:
formatted[0] = '\0';
/* FALL-THROUGH */
case 0:
return(formatted);
}
char* end;
end = innobase_convert_name(formatted, formatted_size,
name, strlen(name), NULL);
/* If the space in 'formatted' was completely used, then sacrifice
the last character in order to write '\0' at the end. */
if ((ulint) (end - formatted) == formatted_size) {
end--;
}
ut_a((ulint) (end - formatted) < formatted_size);
*end = '\0';
return(formatted);
}
/**********************************************************************//**
Catenate files. */
void

View File

@@ -45,6 +45,7 @@ C_MODE_END
#include "key.h"
#include "log.h"
#include "sql_parse.h"
#include "mysql/service_print_check_msg.h"
#include "debug.h"
/*
@@ -428,10 +429,8 @@ static void _ma_check_print_msg(HA_CHECK *param, const LEX_CSTRING *msg_type,
const char *fmt, va_list args)
{
THD *thd= (THD *) param->thd;
Protocol *protocol= thd->protocol;
size_t length, msg_length;
size_t msg_length __attribute__((unused));
char msgbuf[MYSQL_ERRMSG_SIZE];
char name[NAME_LEN * 2 + 2];
if (param->testflag & T_SUPPRESS_ERR_HANDLING)
return;
@@ -460,27 +459,10 @@ static void _ma_check_print_msg(HA_CHECK *param, const LEX_CSTRING *msg_type,
_ma_check_print(param, msg_type, msgbuf);
return;
}
length= (uint) (strxmov(name, param->db_name, ".", param->table_name,
NullS) - name);
/*
TODO: switch from protocol to push_warning here. The main reason we didn't
it yet is parallel repair, which threads have no THD object accessible via
current_thd.
Also we likely need to lock mutex here (in both cases with protocol and
push_warning).
*/
protocol->prepare_for_resend();
protocol->store(name, (uint)length, system_charset_info);
protocol->store(param->op_name, strlen(param->op_name), system_charset_info);
protocol->store(msg_type, system_charset_info);
protocol->store(msgbuf, msg_length, system_charset_info);
if (protocol->write())
sql_print_error("Failed on my_net_write, writing to stderr instead: %s.%s: %s\n",
param->db_name, param->table_name, msgbuf);
else if (thd->variables.log_warnings > 2)
print_check_msg(thd, param->db_name, param->table_name,
param->op_name, msg_type->str, msgbuf, 0);
if (thd->variables.log_warnings > 2)
_ma_check_print(param, msg_type, msgbuf);
return;
}

View File

@@ -59,7 +59,7 @@ struct st_row_applier_status {
enum_rpl_yes_no service_state;
uint remaining_delay;
bool remaining_delay_is_set;
ulong count_transactions_retries;
ulonglong count_transactions_retries;
};
/** Table PERFORMANCE_SCHEMA.replication_applier_status */

View File

@@ -0,0 +1,4 @@
set @old_old_mode=@@global.old_mode;
set global old_mode=4;
INSTALL SONAME 'ha_spider.so';
set global old_mode=@old_old_mode;

View File

@@ -0,0 +1,6 @@
set @old_old_mode=@@global.old_mode;
set global old_mode=4;
INSTALL SONAME 'ha_spider.so';
set global old_mode=@old_old_mode;
--disable_query_log
--source ../../include/clean_up_spider.inc

View File

@@ -19,8 +19,10 @@ eval create table t0 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "$srv",
eval alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "$srv",TABLE "t0"';
--error 12719
select * from t0;
--replace_result test.t1 test.t0 test.t2 test.t0
--error 12719
select * from t1;
--replace_result test.t1 test.t0 test.t2 test.t0
--error 12719
select * from t2;
drop table t0, t1, t2;

View File

@@ -23,6 +23,9 @@ static LEX_STRING spider_init_queries[] = {
{C_STRING_WITH_LEN(
"SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'ORACLE', '');"
)},
{C_STRING_WITH_LEN(
"SET @@OLD_MODE = CONCAT(@@OLD_MODE, ',UTF8_IS_UTF8MB3');"
)},
{C_STRING_WITH_LEN(
"create table if not exists mysql.spider_xa("
" format_id int not null default 0,"