Skip to content
Permalink
Browse files
Merge 10.5 into 10.6
  • Loading branch information
dr-m committed Feb 9, 2022
2 parents 1bed564 + fd101da commit cce9940
Show file tree
Hide file tree
Showing 21 changed files with 253 additions and 99 deletions.
@@ -31,7 +31,7 @@ extern ulong my_time_to_wait_for_lock;
#include <signal.h>
#ifdef HAVE_SIGHANDLER_T
#define sig_return sighandler_t
#elif defined(SOLARIS) || defined(__sun) || defined(__APPLE__) || defined(__FreeBSD__)
#elif defined(SOLARIS) || defined(__sun) || defined(__APPLE__) || defined(__FreeBSD__) || defined(_AIX)
typedef void (*sig_return)(int); /* Returns type from signal */
#else
typedef void (*sig_return)(void); /* Returns type from signal */
@@ -39,6 +39,28 @@ MDL_INTENTION_EXCLUSIVE Schema metadata lock test
select * from t1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
backup unlock;
connection con1;
connection default;
#
# Check that BACKUP LOCK blocks some operations
#
create sequence seq1;
create sequence seq2;
backup lock seq1;
connection con1;
CREATE OR REPLACE SEQUENCE seq1 START -28;
ERROR HY000: Sequence 'test.seq1' values are conflicting
SET STATEMENT max_statement_time=10 FOR CREATE OR REPLACE SEQUENCE seq1 START 50;
ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
SET STATEMENT max_statement_time=10 FOR ALTER SEQUENCE IF EXISTS seq1 NOMAXVALUE;
ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
SET STATEMENT max_statement_time=10 FOR ALTER SEQUENCE IF EXISTS seq1 MAXVALUE 1000;
ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
SET STATEMENT max_statement_time=10 for rename table seq2 to seq3, seq3 to seq1;
ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
connection default;
backup unlock;
drop table seq1,seq2;
#
# BACKUP LOCK and BACKUP UNLOCK are not allowed in procedures.
#
@@ -141,7 +163,6 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
SET STATEMENT max_statement_time=180 FOR BACKUP LOCK test.u;
# restart
#
connection con1;
connection default;
disconnect con1;
show tables;
@@ -43,10 +43,39 @@ SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.me
--error ER_LOCK_DEADLOCK
select * from t1;
backup unlock;
connection con1;
--reap
connection default;

--echo #
--echo # Check that BACKUP LOCK blocks some operations
--echo #

# These test has to be done with timeouts as we want to ensure that the tables
# doesn't change

create sequence seq1;
create sequence seq2;
backup lock seq1;
connection con1;
--error ER_SEQUENCE_INVALID_DATA
CREATE OR REPLACE SEQUENCE seq1 START -28;
--error ER_STATEMENT_TIMEOUT
SET STATEMENT max_statement_time=10 FOR CREATE OR REPLACE SEQUENCE seq1 START 50;
--error ER_STATEMENT_TIMEOUT
SET STATEMENT max_statement_time=10 FOR ALTER SEQUENCE IF EXISTS seq1 NOMAXVALUE;
--error ER_STATEMENT_TIMEOUT
SET STATEMENT max_statement_time=10 FOR ALTER SEQUENCE IF EXISTS seq1 MAXVALUE 1000;
--error ER_STATEMENT_TIMEOUT
SET STATEMENT max_statement_time=10 for rename table seq2 to seq3, seq3 to seq1;
connection default;
backup unlock;
drop table seq1,seq2;

--echo #
--echo # BACKUP LOCK and BACKUP UNLOCK are not allowed in procedures.
--echo #

delimiter |;
--error ER_SP_BADSTATEMENT
CREATE PROCEDURE p_BACKUP_LOCK()
@@ -162,8 +191,6 @@ SET STATEMENT max_statement_time=180 FOR BACKUP LOCK test.u;

--echo #

connection con1;
--reap
connection default;
disconnect con1;
show tables;
@@ -4028,6 +4028,43 @@ drop table t1;
# End of 10.1 tests
#
#
# MDEV-27442 Wrong result upon query with DISTINCT and EXISTS subquery
#
CREATE TABLE t1 (a int, b int, KEY b (b,a)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0,100),(2,100),(2,101),(3,102);
# Must not use Using index for group-by
explain SELECT DISTINCT b FROM t1 WHERE EXISTS ( SELECT 1 FROM DUAL WHERE a > 1 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL b 10 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT DISTINCT b FROM t1 WHERE EXISTS ( SELECT 1 FROM DUAL WHERE a > 1 );
b
100
101
102
DROP TABLE t1;
#
# MDEV-26585 Wrong query results when `using index for group-by`
#
CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_id` int(11) DEFAULT NULL,
`foo` tinyint(1) DEFAULT 0,
`whatever` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_t1_on_owner_id_and_foo` (`owner_id`,`foo`)
) engine=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO t1 (owner_id, foo, whatever)
VALUES (1, TRUE, "yello"), (1, FALSE, "yello"), (2, TRUE, "yello"),
(2, TRUE, "yello"), (2, FALSE, "yello");
EXPLAIN SELECT DISTINCT owner_id FROM t1 WHERE foo = true GROUP BY owner_id HAVING (COUNT(*) = 1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL index_t1_on_owner_id_and_foo 7 NULL 5 Using where; Using index
SELECT DISTINCT owner_id FROM t1 WHERE foo = true GROUP BY owner_id HAVING (COUNT(*) = 1);
owner_id
1
DROP TABLE t1;
#
# MDEV-24353: Adding GROUP BY slows down a query
#
CREATE TABLE t1 (p int NOT NULL, a int NOT NULL, PRIMARY KEY (p,a));
@@ -5,7 +5,7 @@

--source include/default_optimizer_switch.inc
--source include/have_sequence.inc

--source include/have_innodb.inc
#
# TODO:
# Add queries with:
@@ -1691,6 +1691,37 @@ drop table t1;
--echo # End of 10.1 tests
--echo #

--echo #
--echo # MDEV-27442 Wrong result upon query with DISTINCT and EXISTS subquery
--echo #

CREATE TABLE t1 (a int, b int, KEY b (b,a)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0,100),(2,100),(2,101),(3,102);
--echo # Must not use Using index for group-by
explain SELECT DISTINCT b FROM t1 WHERE EXISTS ( SELECT 1 FROM DUAL WHERE a > 1 );
SELECT DISTINCT b FROM t1 WHERE EXISTS ( SELECT 1 FROM DUAL WHERE a > 1 );
DROP TABLE t1;

--echo #
--echo # MDEV-26585 Wrong query results when `using index for group-by`
--echo #

CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_id` int(11) DEFAULT NULL,
`foo` tinyint(1) DEFAULT 0,
`whatever` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_t1_on_owner_id_and_foo` (`owner_id`,`foo`)
) engine=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO t1 (owner_id, foo, whatever)
VALUES (1, TRUE, "yello"), (1, FALSE, "yello"), (2, TRUE, "yello"),
(2, TRUE, "yello"), (2, FALSE, "yello");
EXPLAIN SELECT DISTINCT owner_id FROM t1 WHERE foo = true GROUP BY owner_id HAVING (COUNT(*) = 1);
SELECT DISTINCT owner_id FROM t1 WHERE foo = true GROUP BY owner_id HAVING (COUNT(*) = 1);
DROP TABLE t1;

--echo #
--echo # MDEV-24353: Adding GROUP BY slows down a query
--echo #
@@ -5,6 +5,7 @@ c INT,
INDEX(b))
ENGINE=InnoDB STATS_PERSISTENT=0;
SET GLOBAL innodb_change_buffering_debug = 1;
SET GLOBAL innodb_change_buffering=all;
INSERT INTO t1 SELECT 0,'x',1 FROM seq_1_to_1024;
# restart: --innodb-force-recovery=6 --innodb-change-buffer-dump
check table t1;
@@ -13,6 +13,7 @@ c INT,
INDEX(b))
ENGINE=InnoDB STATS_PERSISTENT=0;
SET GLOBAL innodb_change_buffering_debug = 1;
SET GLOBAL innodb_change_buffering = all;
INSERT INTO t1 SELECT 0,'x',1 FROM seq_1_to_8192;
BEGIN;
SELECT b FROM t1 LIMIT 3;
@@ -24,6 +24,7 @@ ENGINE=InnoDB STATS_PERSISTENT=0;
# change buffering is possible, so that the change buffer will be used
# whenever possible.
SET GLOBAL innodb_change_buffering_debug = 1;
SET GLOBAL innodb_change_buffering=all;

# Create enough rows for the table, so that the change buffer will be
# used for modifying the secondary index page. There must be multiple
@@ -33,6 +33,7 @@ ENGINE=InnoDB STATS_PERSISTENT=0;
# change buffering is possible, so that the change buffer will be used
# whenever possible.
SET GLOBAL innodb_change_buffering_debug = 1;
SET GLOBAL innodb_change_buffering = all;
let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err;

# Create enough rows for the table, so that the change buffer will be
@@ -1,28 +1,28 @@
SET @start_global_value = @@global.innodb_change_buffering;
SELECT @start_global_value;
@start_global_value
all
none
Valid values are 'all', 'deletes', 'changes', 'inserts', 'none', 'purges'
select @@global.innodb_change_buffering in ('all', 'deletes', 'changes', 'inserts', 'none', 'purges');
@@global.innodb_change_buffering in ('all', 'deletes', 'changes', 'inserts', 'none', 'purges')
1
select @@global.innodb_change_buffering;
@@global.innodb_change_buffering
all
none
select @@session.innodb_change_buffering;
ERROR HY000: Variable 'innodb_change_buffering' is a GLOBAL variable
show global variables like 'innodb_change_buffering';
Variable_name Value
innodb_change_buffering all
innodb_change_buffering none
show session variables like 'innodb_change_buffering';
Variable_name Value
innodb_change_buffering all
innodb_change_buffering none
select * from information_schema.global_variables where variable_name='innodb_change_buffering';
VARIABLE_NAME VARIABLE_VALUE
INNODB_CHANGE_BUFFERING all
INNODB_CHANGE_BUFFERING none
select * from information_schema.session_variables where variable_name='innodb_change_buffering';
VARIABLE_NAME VARIABLE_VALUE
INNODB_CHANGE_BUFFERING all
INNODB_CHANGE_BUFFERING none
set global innodb_change_buffering='none';
select @@global.innodb_change_buffering;
@@global.innodb_change_buffering
@@ -62,4 +62,4 @@ ERROR 42000: Variable 'innodb_change_buffering' can't be set to the value of 'so
SET @@global.innodb_change_buffering = @start_global_value;
SELECT @@global.innodb_change_buffering;
@@global.innodb_change_buffering
all
none
@@ -227,7 +227,7 @@ READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_CHANGE_BUFFERING
SESSION_VALUE NULL
DEFAULT_VALUE all
DEFAULT_VALUE none
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE ENUM
VARIABLE_COMMENT Buffer changes to secondary indexes.
@@ -23,6 +23,7 @@

#ifndef MAIN

#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) || defined(__sun) || defined(_WIN32)
static my_bool memcpy_and_test(uchar *to, uchar *from, uint len)
{
uint i, res= 1;
@@ -32,6 +33,7 @@ static my_bool memcpy_and_test(uchar *to, uchar *from, uint len)
res= 0;
return res;
}
#endif

#if defined(__APPLE__) || defined(__FreeBSD__)
#include <net/ethernet.h>
@@ -195,4 +197,3 @@ int main(int argc __attribute__((unused)),char **argv)
return 0;
}
#endif

@@ -1,4 +1,4 @@
/* Copyright (c) 2018, 2020, MariaDB Corporation.
/* Copyright (c) 2018, 2022, 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.
@@ -257,9 +257,13 @@ static bool backup_flush(THD *thd)
This will probably require a callback from the InnoDB code.
*/

/* Retry to get inital lock for 0.1 + 0.5 + 2.25 + 11.25 + 56.25 = 70.35 sec */
#define MAX_RETRY_COUNT 5

static bool backup_block_ddl(THD *thd)
{
PSI_stage_info org_stage;
uint sleep_time;
DBUG_ENTER("backup_block_ddl");

kill_delayed_threads();
@@ -302,18 +306,33 @@ static bool backup_block_ddl(THD *thd)
block new DDL's, in addition to all previous blocks
We didn't do this lock above, as we wanted DDL's to be executed while
we wait for non transactional tables (which may take a while).
We do this lock in a loop as we can get a deadlock if there are multi-object
ddl statements like
RENAME TABLE t1 TO t2, t3 TO t3
and the MDL happens in the middle of it.
*/
THD_STAGE_INFO(thd, stage_waiting_for_ddl);
if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket,
MDL_BACKUP_WAIT_DDL,
thd->variables.lock_wait_timeout))
sleep_time= 100; // Start with 0.1 seconds
for (uint i= 0 ; i <= MAX_RETRY_COUNT ; i++)
{
/*
Could be a timeout. Downgrade lock to what is was before this function
was called so that this function can be called again
*/
backup_flush_ticket->downgrade_lock(MDL_BACKUP_FLUSH);
goto err;
if (!thd->mdl_context.upgrade_shared_lock(backup_flush_ticket,
MDL_BACKUP_WAIT_DDL,
thd->variables.lock_wait_timeout))
break;
if (thd->get_stmt_da()->sql_errno() != ER_LOCK_DEADLOCK || thd->killed ||
i == MAX_RETRY_COUNT)
{
/*
Could be a timeout. Downgrade lock to what is was before this function
was called so that this function can be called again
*/
backup_flush_ticket->downgrade_lock(MDL_BACKUP_FLUSH);
goto err;
}
thd->clear_error(); // Forget the DEADLOCK error
my_sleep(sleep_time);
sleep_time*= 5; // Wait a bit longer next time
}

/* There can't be anything more that needs to be logged to ddl log */
@@ -14039,7 +14039,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
key_part_range[1]= last_part;

/* Check if cur_part is referenced in the WHERE clause. */
if (join->conds->walk(&Item::find_item_in_field_list_processor, 0,
if (join->conds->walk(&Item::find_item_in_field_list_processor, true,
key_part_range))
{
cause= "keypart reference from where clause";

0 comments on commit cce9940

Please sign in to comment.