summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-07-27 10:47:17 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-07-27 10:47:17 +0300
commitf50eb0d398f5f5eb2110192be436e70acd44cb9d (patch)
tree10474699ef727691212dda1cd07fb224c1198770
parent2575eaa502b4253181651decfda46beef7f3f026 (diff)
parentafe00bb7cce7de279e48a83ededc71b3f8cfafcf (diff)
downloadmariadb-git-f50eb0d398f5f5eb2110192be436e70acd44cb9d.tar.gz
Merge 10.2 into 10.3
-rw-r--r--include/my_sys.h5
-rw-r--r--mysql-test/main/cte_recursive.result22
-rw-r--r--mysql-test/main/cte_recursive.test14
-rw-r--r--mysql-test/main/lock_multi_bug38499.test3
-rw-r--r--mysql-test/main/lock_multi_bug38691.test2
-rw-r--r--mysql-test/suite/binlog_encryption/encrypted_master.test3
-rw-r--r--mysql-test/suite/encryption/t/innodb-page_encryption.test3
-rw-r--r--mysql-test/suite/encryption/t/innodb_encryption_filekeys.test18
-rw-r--r--mysql-test/suite/galera/r/galera_fk_lock_wait.result52
-rw-r--r--mysql-test/suite/galera/t/galera_fk_lock_wait.test40
-rw-r--r--mysql-test/suite/gcol/r/innodb_virtual_fk.result3
-rw-r--r--mysql-test/suite/gcol/t/innodb_virtual_fk.test3
-rw-r--r--mysql-test/suite/innodb/t/innodb-page_compression_lz4.test2
-rw-r--r--mysys/mf_qsort.c2
-rw-r--r--storage/innobase/btr/btr0scrub.cc16
-rw-r--r--storage/innobase/fil/fil0crypt.cc34
-rw-r--r--storage/innobase/handler/ha_innodb.cc50
-rw-r--r--storage/innobase/handler/handler0alter.cc3
-rw-r--r--storage/innobase/include/btr0scrub.h7
-rw-r--r--storage/innobase/include/trx0i_s.h6
-rw-r--r--storage/innobase/include/trx0sys.h2
-rw-r--r--storage/innobase/include/trx0trx.h106
-rw-r--r--storage/innobase/include/trx0trx.ic10
-rw-r--r--storage/innobase/lock/lock0lock.cc36
-rw-r--r--storage/innobase/os/os0file.cc4
-rw-r--r--storage/innobase/read/read0read.cc4
-rw-r--r--storage/innobase/row/row0ins.cc4
-rw-r--r--storage/innobase/row/row0upd.cc76
-rw-r--r--storage/innobase/trx/trx0i_s.cc21
-rw-r--r--storage/innobase/trx/trx0roll.cc25
-rw-r--r--storage/innobase/trx/trx0trx.cc63
-rw-r--r--storage/oqgraph/mysql-test/oqgraph/social.test3
-rw-r--r--storage/tokudb/ha_tokudb.cc4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/bug-23786.result10
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/bug-23786.test14
35 files changed, 402 insertions, 268 deletions
diff --git a/include/my_sys.h b/include/my_sys.h
index 020f20926ff..68dad1a63c4 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2019, MariaDB Corporation.
+ Copyright (c) 2010, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -283,7 +283,8 @@ extern int my_umask_dir,
extern my_bool my_use_symdir;
extern ulong my_default_record_cache_size;
-extern my_bool my_disable_locking, my_disable_async_io,
+extern MYSQL_PLUGIN_IMPORT my_bool my_disable_locking;
+extern my_bool my_disable_async_io,
my_disable_flush_key_blocks, my_disable_symlinks;
extern my_bool my_disable_sync, my_disable_copystat_in_redel;
extern char wild_many,wild_one,wild_prefix;
diff --git a/mysql-test/main/cte_recursive.result b/mysql-test/main/cte_recursive.result
index 7bfb0876103..86d5fa08b1f 100644
--- a/mysql-test/main/cte_recursive.result
+++ b/mysql-test/main/cte_recursive.result
@@ -4565,6 +4565,28 @@ drop procedure sp1;
drop procedure sp2;
drop table t1;
#
+# MDEV-26202: Recursive CTE used indirectly twice
+# (fixed by the patch forMDEV-26025)
+#
+with recursive
+rcte as ( SELECT 1 AS a
+UNION ALL
+SELECT cast(a + 1 as unsigned int) FROM rcte WHERE a < 3),
+cte1 AS (SELECT a FROM rcte),
+cte2 AS (SELECT a FROM cte1),
+cte3 AS ( SELECT a FROM cte2)
+SELECT * FROM cte2, cte3;
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+#
# End of 10.2 tests
#
#
diff --git a/mysql-test/main/cte_recursive.test b/mysql-test/main/cte_recursive.test
index d9dc1481f18..4c4bd99c24c 100644
--- a/mysql-test/main/cte_recursive.test
+++ b/mysql-test/main/cte_recursive.test
@@ -2920,6 +2920,20 @@ drop procedure sp2;
drop table t1;
--echo #
+--echo # MDEV-26202: Recursive CTE used indirectly twice
+--echo # (fixed by the patch forMDEV-26025)
+--echo #
+
+with recursive
+ rcte as ( SELECT 1 AS a
+ UNION ALL
+ SELECT cast(a + 1 as unsigned int) FROM rcte WHERE a < 3),
+ cte1 AS (SELECT a FROM rcte),
+ cte2 AS (SELECT a FROM cte1),
+ cte3 AS ( SELECT a FROM cte2)
+SELECT * FROM cte2, cte3;
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/main/lock_multi_bug38499.test b/mysql-test/main/lock_multi_bug38499.test
index b812984e516..c489712e5d8 100644
--- a/mysql-test/main/lock_multi_bug38499.test
+++ b/mysql-test/main/lock_multi_bug38499.test
@@ -2,6 +2,9 @@
# MySQL >= 5.0
#
+# The test can take hours with valgrind
+--source include/not_valgrind.inc
+
# Save the initial number of concurrent sessions
--source include/count_sessions.inc
diff --git a/mysql-test/main/lock_multi_bug38691.test b/mysql-test/main/lock_multi_bug38691.test
index 881a0d8e502..9760c1a873a 100644
--- a/mysql-test/main/lock_multi_bug38691.test
+++ b/mysql-test/main/lock_multi_bug38691.test
@@ -4,6 +4,8 @@
# MySQL >= 5.0
#
+# The test can take hours with valgrind
+--source include/not_valgrind.inc
# Save the initial number of concurrent sessions
--source include/count_sessions.inc
diff --git a/mysql-test/suite/binlog_encryption/encrypted_master.test b/mysql-test/suite/binlog_encryption/encrypted_master.test
index f67e93ce815..f6fc172c79e 100644
--- a/mysql-test/suite/binlog_encryption/encrypted_master.test
+++ b/mysql-test/suite/binlog_encryption/encrypted_master.test
@@ -18,6 +18,9 @@
# - with annotated events, default checksums and minimal binlog row image
#
+# The test can take very long time with valgrind
+--source include/not_valgrind.inc
+
--source include/have_partition.inc
--source encryption_algorithms.inc
--source include/have_innodb.inc
diff --git a/mysql-test/suite/encryption/t/innodb-page_encryption.test b/mysql-test/suite/encryption/t/innodb-page_encryption.test
index df2d1d52aaa..d756f07aea0 100644
--- a/mysql-test/suite/encryption/t/innodb-page_encryption.test
+++ b/mysql-test/suite/encryption/t/innodb-page_encryption.test
@@ -1,6 +1,9 @@
-- source include/have_innodb.inc
-- source include/have_file_key_management_plugin.inc
+# The test can take very long time with valgrind
+--source include/not_valgrind.inc
+
create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb;
show warnings;
create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact encrypted=yes encryption_key_id=1;
diff --git a/mysql-test/suite/encryption/t/innodb_encryption_filekeys.test b/mysql-test/suite/encryption/t/innodb_encryption_filekeys.test
index cd5724638b1..03447bbcfa6 100644
--- a/mysql-test/suite/encryption/t/innodb_encryption_filekeys.test
+++ b/mysql-test/suite/encryption/t/innodb_encryption_filekeys.test
@@ -48,12 +48,6 @@ while ($cnt)
{
real_sleep 1;
dec $cnt;
- if ($cnt == 200)
- {
- --disable_query_log
- set global innodb_encrypt_tables = on;
- --enable_query_log
- }
}
}
if (!$success)
@@ -84,12 +78,6 @@ while ($cnt)
{
real_sleep 1;
dec $cnt;
- if ($cnt == 200)
- {
- --disable_query_log
- set global innodb_encrypt_tables = off;
- --enable_query_log
- }
}
}
if (!$success)
@@ -119,12 +107,6 @@ while ($cnt)
{
real_sleep 1;
dec $cnt;
- if ($cnt == 200)
- {
- --disable_query_log
- set global innodb_encrypt_tables=on;
- --enable_query_log
- }
}
}
if (!$success)
diff --git a/mysql-test/suite/galera/r/galera_fk_lock_wait.result b/mysql-test/suite/galera/r/galera_fk_lock_wait.result
new file mode 100644
index 00000000000..7bbbf40cb29
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_fk_lock_wait.result
@@ -0,0 +1,52 @@
+CREATE TABLE parent(parent_id int not null AUTO_INCREMENT PRIMARY KEY,
+parent_name varchar(80)) ENGINE=InnoDB;
+CREATE TABLE child(child_id int not null AUTO_INCREMENT PRIMARY KEY,
+child_name varchar(80),
+child_parent_id int not null,
+CONSTRAINT `fk_child_parent`
+ FOREIGN KEY (child_parent_id) REFERENCES parent (parent_id)
+ON DELETE CASCADE
+ON UPDATE CASCADE) ENGINE=InnoDB;
+INSERT INTO parent VALUES (1, 'first'),(2,'second'),(3,'foo'),(4,'tmp');
+INSERT INTO child VALUES (NULL,'first_child',1);
+INSERT INTO child VALUES (NULL,'second_child',1);
+INSERT INTO child VALUES (NULL,'first_child2',2);
+INSERT INTO child VALUES (NULL,'first_child3',2);
+INSERT INTO child VALUES (NULL,'first_child4',3);
+BEGIN;
+UPDATE parent SET parent_name = 'bar' WHERE parent_id = 2;
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET SESSION innodb_lock_wait_timeout=2;
+UPDATE child SET child_parent_id = 5 where child_parent_id = 2;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+connection node_1;
+COMMIT;
+SELECT * FROM parent;
+parent_id parent_name
+1 first
+2 bar
+3 foo
+4 tmp
+SELECT * FROM child;
+child_id child_name child_parent_id
+1 first_child 1
+3 second_child 1
+5 first_child2 2
+7 first_child3 2
+9 first_child4 3
+connection node_2;
+SELECT * FROM parent;
+parent_id parent_name
+1 first
+2 bar
+3 foo
+4 tmp
+SELECT * FROM child;
+child_id child_name child_parent_id
+1 first_child 1
+3 second_child 1
+5 first_child2 2
+7 first_child3 2
+9 first_child4 3
+DROP TABLE child, parent;
+disconnect node_1a;
diff --git a/mysql-test/suite/galera/t/galera_fk_lock_wait.test b/mysql-test/suite/galera/t/galera_fk_lock_wait.test
new file mode 100644
index 00000000000..150c7397f7e
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_fk_lock_wait.test
@@ -0,0 +1,40 @@
+--source include/galera_cluster.inc
+
+CREATE TABLE parent(parent_id int not null AUTO_INCREMENT PRIMARY KEY,
+parent_name varchar(80)) ENGINE=InnoDB;
+
+CREATE TABLE child(child_id int not null AUTO_INCREMENT PRIMARY KEY,
+child_name varchar(80),
+child_parent_id int not null,
+CONSTRAINT `fk_child_parent`
+ FOREIGN KEY (child_parent_id) REFERENCES parent (parent_id)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE) ENGINE=InnoDB;
+
+INSERT INTO parent VALUES (1, 'first'),(2,'second'),(3,'foo'),(4,'tmp');
+INSERT INTO child VALUES (NULL,'first_child',1);
+INSERT INTO child VALUES (NULL,'second_child',1);
+INSERT INTO child VALUES (NULL,'first_child2',2);
+INSERT INTO child VALUES (NULL,'first_child3',2);
+INSERT INTO child VALUES (NULL,'first_child4',3);
+
+BEGIN;
+UPDATE parent SET parent_name = 'bar' WHERE parent_id = 2;
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION innodb_lock_wait_timeout=2;
+--error ER_LOCK_WAIT_TIMEOUT
+UPDATE child SET child_parent_id = 5 where child_parent_id = 2;
+
+--connection node_1
+COMMIT;
+SELECT * FROM parent;
+SELECT * FROM child;
+
+--connection node_2
+
+SELECT * FROM parent;
+SELECT * FROM child;
+DROP TABLE child, parent;
+
+--disconnect node_1a
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_fk.result b/mysql-test/suite/gcol/r/innodb_virtual_fk.result
index 252274f3e0a..367ed1223f7 100644
--- a/mysql-test/suite/gcol/r/innodb_virtual_fk.result
+++ b/mysql-test/suite/gcol/r/innodb_virtual_fk.result
@@ -809,15 +809,18 @@ generated_email_id int as (email_id),
PRIMARY KEY (id),
KEY mautic_generated_sent_date_email_id (generated_email_id),
FOREIGN KEY (email_id) REFERENCES emails (id) ON DELETE SET NULL
+ON UPDATE CASCADE
) ENGINE=InnoDB;
CREATE TABLE emails_metadata (
email_id int,
PRIMARY KEY (email_id),
CONSTRAINT FK FOREIGN KEY (email_id) REFERENCES emails (id) ON DELETE CASCADE
+ON UPDATE CASCADE
) ENGINE=InnoDB;
INSERT INTO emails VALUES (1);
INSERT INTO email_stats (id, email_id, date_sent) VALUES (1,1,'Jan');
INSERT INTO emails_metadata VALUES (1);
+UPDATE emails SET id=2;
DELETE FROM emails;
DROP TABLE email_stats;
DROP TABLE emails_metadata;
diff --git a/mysql-test/suite/gcol/t/innodb_virtual_fk.test b/mysql-test/suite/gcol/t/innodb_virtual_fk.test
index 24b6a4631e6..c99259531b3 100644
--- a/mysql-test/suite/gcol/t/innodb_virtual_fk.test
+++ b/mysql-test/suite/gcol/t/innodb_virtual_fk.test
@@ -670,6 +670,7 @@ CREATE TABLE email_stats (
PRIMARY KEY (id),
KEY mautic_generated_sent_date_email_id (generated_email_id),
FOREIGN KEY (email_id) REFERENCES emails (id) ON DELETE SET NULL
+ ON UPDATE CASCADE
) ENGINE=InnoDB;
@@ -677,6 +678,7 @@ CREATE TABLE emails_metadata (
email_id int,
PRIMARY KEY (email_id),
CONSTRAINT FK FOREIGN KEY (email_id) REFERENCES emails (id) ON DELETE CASCADE
+ ON UPDATE CASCADE
) ENGINE=InnoDB;
@@ -684,6 +686,7 @@ INSERT INTO emails VALUES (1);
INSERT INTO email_stats (id, email_id, date_sent) VALUES (1,1,'Jan');
INSERT INTO emails_metadata VALUES (1);
+UPDATE emails SET id=2;
DELETE FROM emails;
DROP TABLE email_stats;
diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test b/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test
index 49255d3a1ac..ec9bc456e74 100644
--- a/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test
+++ b/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test
@@ -1,6 +1,8 @@
-- source include/have_innodb.inc
-- source include/have_innodb_lz4.inc
-- source include/not_embedded.inc
+# The test can take very long time with valgrind
+--source include/not_valgrind.inc
# lz4
set global innodb_compression_algorithm = 2;
diff --git a/mysys/mf_qsort.c b/mysys/mf_qsort.c
index 3f91bb35354..b516639a341 100644
--- a/mysys/mf_qsort.c
+++ b/mysys/mf_qsort.c
@@ -114,7 +114,7 @@ qsort_t my_qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp)
stack[0].low=stack[0].high=0;
#endif
pivot = (char *) my_alloca((int) size);
- ptr_cmp= size == sizeof(char*) && !((low - (char*) 0)& (sizeof(char*)-1));
+ ptr_cmp= size == sizeof(char*) && (intptr_t)low % sizeof(char*) == 0;
/* The following loop sorts elements between high and low */
do
diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc
index 6a550739121..74969e1f39a 100644
--- a/storage/innobase/btr/btr0scrub.cc
+++ b/storage/innobase/btr/btr0scrub.cc
@@ -1,5 +1,5 @@
// Copyright (c) 2014, Google Inc.
-// Copyright (c) 2017, MariaDB Corporation.
+// Copyright (c) 2017, 2021, MariaDB Corporation.
/**************************************************//**
@file btr/btr0scrub.cc
@@ -830,20 +830,12 @@ btr_scrub_page(
/**************************************************************//**
Start iterating a space */
-UNIV_INTERN
-bool
-btr_scrub_start_space(
-/*===================*/
- ulint space, /*!< in: space */
- btr_scrub_t* scrub_data) /*!< in/out: scrub data */
+bool btr_scrub_start_space(const fil_space_t &space, btr_scrub_t *scrub_data)
{
- bool found;
- scrub_data->space = space;
+ scrub_data->space = space.id;
scrub_data->current_table = NULL;
scrub_data->current_index = NULL;
- const page_size_t page_size = fil_space_get_page_size(space, &found);
-
- scrub_data->compressed = page_size.is_compressed();
+ scrub_data->compressed = FSP_FLAGS_GET_ZIP_SSIZE(space.flags) != 0;
scrub_data->scrubbing = check_scrub_setting(scrub_data);
return scrub_data->scrubbing;
}
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index bf428c19191..f63b75a0e44 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
-Copyright (c) 2014, 2020, MariaDB Corporation.
+Copyright (c) 2014, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1091,6 +1091,33 @@ struct rotate_thread_t {
}
};
+/** Avoid the removal of the tablespace from
+default_encrypt_list only when
+1) Another active encryption thread working on tablespace
+2) Eligible for tablespace key rotation
+3) Tablespace is in flushing phase
+@return true if tablespace should be removed from
+default encrypt */
+static bool fil_crypt_must_remove(const fil_space_t &space)
+{
+ ut_ad(space.purpose == FIL_TYPE_TABLESPACE);
+ fil_space_crypt_t *crypt_data = space.crypt_data;
+ ut_ad(mutex_own(&fil_system.mutex));
+ const ulong encrypt_tables= srv_encrypt_tables;
+ if (!crypt_data)
+ return !encrypt_tables;
+ if (!crypt_data->is_key_found())
+ return true;
+
+ mutex_enter(&crypt_data->mutex);
+ const bool remove= (space.is_stopping() || crypt_data->not_encrypted()) &&
+ (!crypt_data->rotate_state.flushing &&
+ !encrypt_tables == !!crypt_data->min_key_version &&
+ !crypt_data->rotate_state.active_threads);
+ mutex_exit(&crypt_data->mutex);
+ return remove;
+}
+
/***********************************************************************
Check if space needs rotation given a key_state
@param[in,out] state Key rotation state
@@ -1172,7 +1199,7 @@ fil_crypt_space_needs_rotation(
key_state->rotate_key_age);
crypt_data->rotate_state.scrubbing.is_active =
- btr_scrub_start_space(space->id, &state->scrub_data);
+ btr_scrub_start_space(*space, &state->scrub_data);
time_t diff = time(0) - crypt_data->rotate_state.scrubbing.
last_scrub_completed;
@@ -1428,8 +1455,7 @@ inline fil_space_t *fil_system_t::default_encrypt_next(
If there is a change in innodb_encrypt_tables variables
value then don't remove the last processed tablespace
from the default encrypt list. */
- if (released && (!recheck || space->crypt_data) &&
- !encrypt == !srv_encrypt_tables)
+ if (released && !recheck && fil_crypt_must_remove(*space))
{
ut_a(!default_encrypt_tables.empty());
default_encrypt_tables.remove(*space);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 65039919793..79f154dfe13 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -4441,7 +4441,7 @@ innobase_commit_low(
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
} else {
- trx->will_lock = 0;
+ trx->will_lock = false;
#ifdef WITH_WSREP
trx->wsrep = false;
#endif /* WITH_WSREP */
@@ -4795,7 +4795,7 @@ innobase_rollback_trx(
lock_unlock_table_autoinc(trx);
if (!trx->has_logged()) {
- trx->will_lock = 0;
+ trx->will_lock = false;
#ifdef WITH_WSREP
trx->wsrep = false;
#endif
@@ -8066,7 +8066,7 @@ ha_innobase::write_row(
ut_a(m_prebuilt->trx == trx);
if (!trx_is_started(trx)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
#ifdef WITH_WSREP
@@ -8842,7 +8842,7 @@ ha_innobase::update_row(
ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
DBUG_RETURN(HA_ERR_TABLE_READONLY);
} else if (!trx_is_started(trx)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
if (m_upd_buf == NULL) {
@@ -9021,7 +9021,7 @@ ha_innobase::delete_row(
ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
DBUG_RETURN(HA_ERR_TABLE_READONLY);
} else if (!trx_is_started(trx)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
if (!m_prebuilt->upd_node) {
@@ -9899,7 +9899,7 @@ ha_innobase::ft_init()
them as regular read only transactions for now. */
if (!trx_is_started(trx)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
DBUG_RETURN(rnd_init(false));
@@ -9965,7 +9965,7 @@ ha_innobase::ft_init_ext(
them as regular read only transactions for now. */
if (!trx_is_started(trx)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
dict_table_t* ft_table = m_prebuilt->table;
@@ -12893,7 +12893,7 @@ create_table_info_t::allocate_trx()
{
m_trx = innobase_trx_allocate(m_thd);
- m_trx->will_lock++;
+ m_trx->will_lock = true;
m_trx->ddl = true;
}
@@ -13207,13 +13207,7 @@ inline int ha_innobase::delete_table(const char* name, enum_sql_command sqlcom)
ut_a(name_len < 1000);
- /* Either the transaction is already flagged as a locking transaction
- or it hasn't been started yet. */
-
- ut_a(!trx_is_started(trx) || trx->will_lock > 0);
-
- /* We are doing a DDL operation. */
- ++trx->will_lock;
+ trx->will_lock = true;
/* Drop the table in InnoDB */
@@ -13390,14 +13384,7 @@ innobase_drop_database(
#endif /* _WIN32 */
trx_t* trx = innobase_trx_allocate(thd);
-
- /* Either the transaction is already flagged as a locking transaction
- or it hasn't been started yet. */
-
- ut_a(!trx_is_started(trx) || trx->will_lock > 0);
-
- /* We are doing a DDL operation. */
- ++trx->will_lock;
+ trx->will_lock = true;
ulint dummy;
@@ -13441,7 +13428,7 @@ inline dberr_t innobase_rename_table(trx_t *trx, const char *from,
DEBUG_SYNC_C("innodb_rename_table_ready");
trx_start_if_not_started(trx, true);
- ut_ad(trx->will_lock > 0);
+ ut_ad(trx->will_lock);
if (commit) {
/* Serialize data dictionary operations with dictionary mutex:
@@ -13590,8 +13577,7 @@ int ha_innobase::truncate()
heap, ib_table->name.m_name, ib_table->id);
const char* name = mem_heap_strdup(heap, ib_table->name.m_name);
trx_t* trx = innobase_trx_allocate(m_user_thd);
-
- ++trx->will_lock;
+ trx->will_lock = true;
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
row_mysql_lock_data_dictionary(trx);
dict_stats_wait_bg_to_stop_using_table(ib_table, trx);
@@ -13676,9 +13662,7 @@ ha_innobase::rename_table(
}
trx_t* trx = innobase_trx_allocate(thd);
-
- /* We are doing a DDL operation. */
- ++trx->will_lock;
+ trx->will_lock = true;
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
dberr_t error = innobase_rename_table(trx, from, to, true);
@@ -15673,7 +15657,7 @@ ha_innobase::start_stmt(
innobase_register_trx(ht, thd, trx);
if (!trx_is_started(trx)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
DBUG_RETURN(0);
@@ -15900,7 +15884,7 @@ ha_innobase::external_lock(
&& (m_prebuilt->select_lock_type != LOCK_NONE
|| m_prebuilt->stored_select_lock_type != LOCK_NONE)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
DBUG_RETURN(0);
@@ -15941,7 +15925,7 @@ ha_innobase::external_lock(
&& (m_prebuilt->select_lock_type != LOCK_NONE
|| m_prebuilt->stored_select_lock_type != LOCK_NONE)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
DBUG_RETURN(0);
@@ -16623,7 +16607,7 @@ ha_innobase::store_lock(
&& (m_prebuilt->select_lock_type != LOCK_NONE
|| m_prebuilt->stored_select_lock_type != LOCK_NONE)) {
- ++trx->will_lock;
+ trx->will_lock = true;
}
return(to);
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 85025aae5be..30547dc5f2d 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1369,7 +1369,7 @@ ha_innobase::check_if_supported_inplace_alter(
}
}
- m_prebuilt->trx->will_lock++;
+ m_prebuilt->trx->will_lock = true;
/* When changing a NULL column to NOT NULL and specifying a
DEFAULT value, ensure that the DEFAULT expression is a constant.
@@ -10131,7 +10131,6 @@ foreign_fail:
m_prebuilt = ctx->prebuilt;
}
trx_start_if_not_started(user_trx, true);
- user_trx->will_lock++;
m_prebuilt->trx = user_trx;
}
DBUG_INJECT_CRASH("ib_commit_inplace_crash",
diff --git a/storage/innobase/include/btr0scrub.h b/storage/innobase/include/btr0scrub.h
index feaf61784d0..0f17467fb70 100644
--- a/storage/innobase/include/btr0scrub.h
+++ b/storage/innobase/include/btr0scrub.h
@@ -141,12 +141,7 @@ btr_scrub_skip_page(
/****************************************************************
Start iterating a space
* @return true if scrubbing is turned on */
-UNIV_INTERN
-bool
-btr_scrub_start_space(
-/*===================*/
- ulint space, /*!< in: space */
- btr_scrub_t* scrub_data); /*!< in/out: scrub data */
+bool btr_scrub_start_space(const fil_space_t &space, btr_scrub_t *scrub_data);
/** Complete iterating a space.
@param[in,out] scrub_data scrub data */
diff --git a/storage/innobase/include/trx0i_s.h b/storage/innobase/include/trx0i_s.h
index 65c7d321597..ea2f9a18fcc 100644
--- a/storage/innobase/include/trx0i_s.h
+++ b/storage/innobase/include/trx0i_s.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2019, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -164,8 +164,8 @@ struct i_s_trx_row_t {
/*!< detailed_error in trx_t */
ulint trx_is_read_only;
/*!< trx_t::read_only */
- ulint trx_is_autocommit_non_locking;
- /*!< trx_is_autocommit_non_locking(trx)
+ bool trx_is_autocommit_non_locking;
+ /*!< trx:t::is_autocommit_non_locking()
*/
};
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index 35ac8e12001..c06afb927cb 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -512,7 +512,7 @@ class rw_trx_hash_t
static void validate_element(trx_t *trx)
{
ut_ad(!trx->read_only || !trx->rsegs.m_redo.rseg);
- ut_ad(!trx_is_autocommit_non_locking(trx));
+ ut_ad(!trx->is_autocommit_non_locking());
/* trx->state can be anything except TRX_STATE_NOT_STARTED */
mutex_enter(&trx->mutex);
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) ||
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index b4ed45f3565..ceb041c0034 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -406,81 +406,6 @@ from innodb_lock_wait_timeout via trx_t::mysql_thd.
? thd_lock_wait_timeout((t)->mysql_thd) \
: 0)
-/**
-Determine if the transaction is a non-locking autocommit select
-(implied read-only).
-@param t transaction
-@return true if non-locking autocommit select transaction. */
-#define trx_is_autocommit_non_locking(t) \
-((t)->auto_commit && (t)->will_lock == 0)
-
-/**
-Determine if the transaction is a non-locking autocommit select
-with an explicit check for the read-only status.
-@param t transaction
-@return true if non-locking autocommit read-only transaction. */
-#define trx_is_ac_nl_ro(t) \
-((t)->read_only && trx_is_autocommit_non_locking((t)))
-
-/**
-Check transaction state */
-#define check_trx_state(t) do { \
- ut_ad(!trx_is_autocommit_non_locking((t))); \
- switch ((t)->state) { \
- case TRX_STATE_PREPARED: \
- case TRX_STATE_PREPARED_RECOVERED: \
- case TRX_STATE_ACTIVE: \
- case TRX_STATE_COMMITTED_IN_MEMORY: \
- continue; \
- case TRX_STATE_NOT_STARTED: \
- break; \
- } \
- ut_error; \
-} while (0)
-
-/** Check if transaction is free so that it can be re-initialized.
-@param t transaction handle */
-#define assert_trx_is_free(t) do { \
- ut_ad(trx_state_eq((t), TRX_STATE_NOT_STARTED)); \
- ut_ad(!(t)->id); \
- ut_ad(!(t)->has_logged()); \
- ut_ad(!(t)->is_referenced()); \
- ut_ad(!(t)->is_wsrep()); \
- ut_ad(!(t)->read_view.is_open()); \
- ut_ad((t)->lock.wait_thr == NULL); \
- ut_ad(UT_LIST_GET_LEN((t)->lock.trx_locks) == 0); \
- ut_ad((t)->lock.table_locks.empty()); \
- ut_ad(!(t)->autoinc_locks \
- || ib_vector_is_empty((t)->autoinc_locks)); \
- ut_ad((t)->dict_operation == TRX_DICT_OP_NONE); \
-} while(0)
-
-#ifdef UNIV_DEBUG
-/*******************************************************************//**
-Assert that an autocommit non-locking select cannot be in the
-rw_trx_hash and that it is a read-only transaction.
-The transaction must have mysql_thd assigned. */
-# define assert_trx_nonlocking_or_in_list(t) \
- do { \
- if (trx_is_autocommit_non_locking(t)) { \
- trx_state_t t_state = (t)->state; \
- ut_ad((t)->read_only); \
- ut_ad(!(t)->is_recovered); \
- ut_ad((t)->mysql_thd); \
- ut_ad(t_state == TRX_STATE_NOT_STARTED \
- || t_state == TRX_STATE_ACTIVE); \
- } else { \
- check_trx_state(t); \
- } \
- } while (0)
-#else /* UNIV_DEBUG */
-/*******************************************************************//**
-Assert that an autocommit non-locking slect cannot be in the
-rw_trx_hash and that it is a read-only transaction.
-The transaction must have mysql_thd assigned. */
-# define assert_trx_nonlocking_or_in_list(trx) ((void)0)
-#endif /* UNIV_DEBUG */
-
typedef std::vector<ib_lock_t*, ut_allocator<ib_lock_t*> > lock_list;
/*******************************************************************//**
@@ -985,16 +910,15 @@ public:
/*------------------------------*/
bool read_only; /*!< true if transaction is flagged
as a READ-ONLY transaction.
- if auto_commit && will_lock == 0
+ if auto_commit && !will_lock
then it will be handled as a
AC-NL-RO-SELECT (Auto Commit Non-Locking
Read Only Select). A read only
transaction will not be assigned an
UNDO log. */
bool auto_commit; /*!< true if it is an autocommit */
- ib_uint32_t will_lock; /*!< Will acquire some locks. Increment
- each time we determine that a lock will
- be acquired by the MySQL layer. */
+ bool will_lock; /*!< set to inform trx_start_low() that
+ the transaction may acquire locks */
/*------------------------------*/
fts_trx_t* fts_trx; /*!< FTS information, or NULL if
transaction hasn't modified tables
@@ -1116,10 +1040,28 @@ public:
void free();
+ void assert_freed() const
+ {
+ ut_ad(state == TRX_STATE_NOT_STARTED);
+ ut_ad(!id);
+ ut_ad(!has_logged());
+ ut_ad(!const_cast<trx_t*>(this)->is_referenced());
+ ut_ad(!is_wsrep());
+ ut_ad(!read_view.is_open());
+ ut_ad(!lock.wait_thr);
+ ut_ad(UT_LIST_GET_LEN(lock.trx_locks) == 0);
+ ut_ad(lock.table_locks.empty());
+ ut_ad(!autoinc_locks || ib_vector_is_empty(autoinc_locks));
+ ut_ad(dict_operation == TRX_DICT_OP_NONE);
+ }
+
+ /** @return whether this is a non-locking autocommit transaction */
+ bool is_autocommit_non_locking() const { return auto_commit && !will_lock; }
+
private:
- /** Assign a rollback segment for modifying temporary tables.
- @return the assigned rollback segment */
- trx_rseg_t* assign_temp_rseg();
+ /** Assign a rollback segment for modifying temporary tables.
+ @return the assigned rollback segment */
+ trx_rseg_t *assign_temp_rseg();
};
/**
diff --git a/storage/innobase/include/trx0trx.ic b/storage/innobase/include/trx0trx.ic
index f51d5368022..72310cbba06 100644
--- a/storage/innobase/include/trx0trx.ic
+++ b/storage/innobase/include/trx0trx.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2019, MariaDB Corporation.
+Copyright (c) 2016, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -49,11 +49,15 @@ trx_state_eq(
case TRX_STATE_PREPARED:
case TRX_STATE_PREPARED_RECOVERED:
case TRX_STATE_COMMITTED_IN_MEMORY:
- ut_ad(!trx_is_autocommit_non_locking(trx));
+ ut_ad(!trx->is_autocommit_non_locking());
return(trx->state == state);
case TRX_STATE_ACTIVE:
- assert_trx_nonlocking_or_in_list(trx);
+ if (trx->is_autocommit_non_locking()) {
+ ut_ad(!trx->is_recovered);
+ ut_ad(trx->read_only);
+ ut_ad(trx->mysql_thd);
+ }
return(state == trx->state);
case TRX_STATE_NOT_STARTED:
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index c584de0fa5d..5c45d38525f 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -1309,6 +1309,19 @@ wsrep_print_wait_locks(
}
#endif /* WITH_WSREP */
+#ifdef UNIV_DEBUG
+/** Check transaction state */
+static void check_trx_state(const trx_t *trx)
+{
+ ut_ad(!trx->auto_commit || trx->will_lock);
+ const trx_state_t state= trx->state;
+ ut_ad(state == TRX_STATE_ACTIVE ||
+ state == TRX_STATE_PREPARED_RECOVERED ||
+ state == TRX_STATE_PREPARED ||
+ state == TRX_STATE_COMMITTED_IN_MEMORY);
+}
+#endif
+
/** Create a new record lock and inserts it to the lock queue,
without checking for deadlocks or conflicts.
@param[in] type_mode lock mode and wait flag; type will be replaced
@@ -3449,8 +3462,8 @@ lock_table_create(
ut_ad(table && trx);
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(trx));
-
- check_trx_state(trx);
+ ut_ad(trx->is_recovered || trx->state == TRX_STATE_ACTIVE);
+ ut_ad(!trx->auto_commit || trx->will_lock);
if ((type_mode & LOCK_MODE_MASK) == LOCK_AUTO_INC) {
++table->n_waiting_or_granted_auto_inc_locks;
@@ -4841,7 +4854,8 @@ lock_rec_queue_validate(
ut_ad(!index || lock->index == index);
trx_mutex_enter(lock->trx);
- ut_ad(!trx_is_ac_nl_ro(lock->trx));
+ ut_ad(!lock->trx->read_only
+ || !lock->trx->is_autocommit_non_locking());
ut_ad(trx_state_eq(lock->trx,
TRX_STATE_COMMITTED_IN_MEMORY)
|| !lock_get_wait(lock)
@@ -4927,8 +4941,8 @@ func_exit:
for (lock = lock_rec_get_first(lock_sys.rec_hash, block, heap_no);
lock != NULL;
lock = lock_rec_get_next_const(heap_no, lock)) {
-
- ut_ad(!trx_is_ac_nl_ro(lock->trx));
+ ut_ad(!lock->trx->read_only
+ || !lock->trx->is_autocommit_non_locking());
ut_ad(!page_rec_is_metadata(rec));
if (index) {
@@ -5018,7 +5032,8 @@ loop:
}
}
- ut_ad(!trx_is_ac_nl_ro(lock->trx));
+ ut_ad(!lock->trx->read_only
+ || !lock->trx->is_autocommit_non_locking());
/* Only validate the record queues when this thread is not
holding a space->latch. */
@@ -5085,7 +5100,8 @@ lock_rec_validate(
ib_uint64_t current;
- ut_ad(!trx_is_ac_nl_ro(lock->trx));
+ ut_ad(!lock->trx->read_only
+ || !lock->trx->is_autocommit_non_locking());
ut_ad(lock_get_type(lock) == LOCK_REC);
current = ut_ull_create(
@@ -6775,7 +6791,8 @@ DeadlockChecker::search()
ut_ad(m_start != NULL);
ut_ad(m_wait_lock != NULL);
- check_trx_state(m_wait_lock->trx);
+ ut_ad(!m_wait_lock->trx->auto_commit || m_wait_lock->trx->will_lock);
+ ut_d(check_trx_state(m_wait_lock->trx));
ut_ad(m_mark_start <= s_lock_mark_counter);
/* Look at the locks ahead of wait_lock in the lock queue. */
@@ -6935,7 +6952,8 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx)
{
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(trx));
- check_trx_state(trx);
+ ut_ad(trx->state == TRX_STATE_ACTIVE);
+ ut_ad(!trx->auto_commit || trx->will_lock);
ut_ad(!srv_read_only_mode);
if (!innobase_deadlock_detect) {
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 811a8c7485a..4ec42eb805a 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -1112,6 +1112,10 @@ os_file_lock(
int fd,
const char* name)
{
+ if (my_disable_locking) {
+ return 0;
+ }
+
struct flock lk;
lk.l_type = F_WRLCK;
diff --git a/storage/innobase/read/read0read.cc b/storage/innobase/read/read0read.cc
index e14f564e264..e84e7d33aaf 100644
--- a/storage/innobase/read/read0read.cc
+++ b/storage/innobase/read/read0read.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2019, MariaDB Corporation.
+Copyright (c) 2018, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -235,7 +235,7 @@ void ReadView::open(trx_t *trx)
may get started, committed and purged meanwhile. It is acceptable as
well, since this view doesn't see it.
*/
- if (trx_is_autocommit_non_locking(trx) && m_ids.empty() &&
+ if (trx->is_autocommit_non_locking() && m_ids.empty() &&
m_low_limit_id == trx_sys.get_max_trx_id())
goto reopen;
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 512d373bbfa..380ef7def31 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -935,8 +935,8 @@ row_ins_foreign_fill_virtual(
upd_field = update->fields + n_diff;
upd_field->old_v_val = static_cast<dfield_t*>(
- mem_heap_alloc(cascade->heap,
- sizeof *upd_field->old_v_val));
+ mem_heap_alloc(update->heap,
+ sizeof *upd_field->old_v_val));
dfield_copy(upd_field->old_v_val, vfield);
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index 600034c8ba3..c4a7f93ed2a 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -52,6 +52,11 @@ Created 12/27/1996 Heikki Tuuri
#include <algorithm>
#include <mysql/plugin.h>
#include <mysql/service_wsrep.h>
+#ifdef WITH_WSREP
+#include "log.h"
+#include "wsrep.h"
+#endif /* WITH_WSREP */
+
/* What kind of latch and lock can we assume when the control comes to
-------------------------------------------------------------------
@@ -2466,34 +2471,30 @@ row_upd_sec_index_entry(
err = DB_SUCCESS;
break;
case DB_LOCK_WAIT:
- if (UNIV_UNLIKELY(wsrep_debug)) {
- ib::warn() << "WSREP: sec index FK lock wait"
- << " index " << index->name
- << " table " << index->table->name
- << " query " << wsrep_thd_query(trx->mysql_thd);
- }
- break;
case DB_DEADLOCK:
- if (UNIV_UNLIKELY(wsrep_debug)) {
- ib::warn() << "WSREP: sec index FK check fail for deadlock"
- << " index " << index->name
- << " table " << index->table->name
- << " query " << wsrep_thd_query(trx->mysql_thd);
- }
+ case DB_LOCK_WAIT_TIMEOUT:
+ WSREP_DEBUG("Foreign key check fail: "
+ "%s on table %s index %s query %s",
+ ut_strerr(err), index->name, index->table->name,
+ wsrep_thd_query(trx->mysql_thd));
break;
default:
- ib::error() << "WSREP: referenced FK check fail: " << err
- << " index " << index->name
- << " table " << index->table->name
- << " query " << wsrep_thd_query(trx->mysql_thd);
-
+ WSREP_ERROR("Foreign key check fail: "
+ "%s on table %s index %s query %s",
+ ut_strerr(err), index->name, index->table->name,
+ wsrep_thd_query(trx->mysql_thd));
break;
}
}
#endif /* WITH_WSREP */
}
+#ifdef WITH_WSREP
+ ut_ad(err == DB_SUCCESS || err == DB_LOCK_WAIT
+ || err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT);
+#else
ut_ad(err == DB_SUCCESS);
+#endif
if (referenced) {
rec_offs* offsets = rec_get_offsets(
@@ -2804,17 +2805,21 @@ check_fk:
case DB_NO_REFERENCED_ROW:
err = DB_SUCCESS;
break;
+ case DB_LOCK_WAIT:
case DB_DEADLOCK:
- if (UNIV_UNLIKELY(wsrep_debug)) {
- ib::warn() << "WSREP: sec index FK check fail for deadlock"
- << " index " << index->name
- << " table " << index->table->name;
- }
+ case DB_LOCK_WAIT_TIMEOUT:
+ WSREP_DEBUG("Foreign key check fail: "
+ "%s on table %s index %s query %s",
+ ut_strerr(err), index->name, index->table->name,
+ wsrep_thd_query(trx->mysql_thd));
+
goto err_exit;
default:
- ib::error() << "WSREP: referenced FK check fail: " << err
- << " index " << index->name
- << " table " << index->table->name;
+ WSREP_ERROR("Foreign key check fail: "
+ "%s on table %s index %s query %s",
+ ut_strerr(err), index->name, index->table->name,
+ wsrep_thd_query(trx->mysql_thd));
+
goto err_exit;
}
#endif /* WITH_WSREP */
@@ -3031,18 +3036,19 @@ row_upd_del_mark_clust_rec(
case DB_NO_REFERENCED_ROW:
err = DB_SUCCESS;
break;
+ case DB_LOCK_WAIT:
case DB_DEADLOCK:
- if (UNIV_UNLIKELY(wsrep_debug)) {
- ib::warn() << "WSREP: sec index FK check fail for deadlock"
- << " index " << index->name
- << " table " << index->table->name;
- }
+ case DB_LOCK_WAIT_TIMEOUT:
+ WSREP_DEBUG("Foreign key check fail: "
+ "%d on table %s index %s query %s",
+ err, index->name, index->table->name,
+ wsrep_thd_query(trx->mysql_thd));
break;
default:
- ib::error() << "WSREP: referenced FK check fail: " << err
- << " index " << index->name
- << " table " << index->table->name;
-
+ WSREP_ERROR("Foreign key check fail: "
+ "%d on table %s index %s query %s",
+ err, index->name, index->table->name,
+ wsrep_thd_query(trx->mysql_thd));
break;
}
#endif /* WITH_WSREP */
diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc
index 59e0bed8006..afd644f3c70 100644
--- a/storage/innobase/trx/trx0i_s.cc
+++ b/storage/innobase/trx/trx0i_s.cc
@@ -578,7 +578,7 @@ thd_done:
row->trx_is_read_only = trx->read_only;
- row->trx_is_autocommit_non_locking = trx_is_autocommit_non_locking(trx);
+ row->trx_is_autocommit_non_locking = trx->is_autocommit_non_locking();
return(TRUE);
}
@@ -1233,7 +1233,24 @@ static void fetch_data_into_cache_low(trx_i_s_cache_t *cache, const trx_t *trx)
{
i_s_locks_row_t *requested_lock_row;
- assert_trx_nonlocking_or_in_list(trx);
+#ifdef UNIV_DEBUG
+ {
+ const trx_state_t state= trx->state;
+
+ if (trx->is_autocommit_non_locking())
+ {
+ ut_ad(trx->read_only);
+ ut_ad(!trx->is_recovered);
+ ut_ad(trx->mysql_thd);
+ ut_ad(state == TRX_STATE_NOT_STARTED || state == TRX_STATE_ACTIVE);
+ }
+ else
+ ut_ad(state == TRX_STATE_ACTIVE ||
+ state == TRX_STATE_PREPARED ||
+ state == TRX_STATE_PREPARED_RECOVERED ||
+ state == TRX_STATE_COMMITTED_IN_MEMORY);
+ }
+#endif /* UNIV_DEBUG */
if (add_trx_relevant_locks_to_cache(cache, trx, &requested_lock_row))
{
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index bffd168359b..4792d03db4b 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -108,12 +108,18 @@ trx_rollback_to_savepoint_low(
heap = mem_heap_create(512);
roll_node = roll_node_create(heap);
+ ut_ad(!trx->in_rollback);
if (savept != NULL) {
roll_node->savept = savept;
- check_trx_state(trx);
+ ut_ad(trx->mysql_thd);
+ ut_ad(!trx->is_recovered);
+ ut_ad(trx->state == TRX_STATE_ACTIVE);
} else {
- assert_trx_nonlocking_or_in_list(trx);
+ ut_d(trx_state_t state = trx->state);
+ ut_ad(state == TRX_STATE_ACTIVE
+ || state == TRX_STATE_PREPARED
+ || state == TRX_STATE_PREPARED_RECOVERED);
}
trx->error_state = DB_SUCCESS;
@@ -219,7 +225,7 @@ dberr_t trx_rollback_for_mysql(trx_t* trx)
switch (trx->state) {
case TRX_STATE_NOT_STARTED:
- trx->will_lock = 0;
+ trx->will_lock = false;
ut_ad(trx->mysql_thd);
#ifdef WITH_WSREP
trx->wsrep = false;
@@ -228,13 +234,14 @@ dberr_t trx_rollback_for_mysql(trx_t* trx)
case TRX_STATE_ACTIVE:
ut_ad(trx->mysql_thd);
- assert_trx_nonlocking_or_in_list(trx);
+ ut_ad(!trx->is_recovered);
+ ut_ad(!trx->is_autocommit_non_locking() || trx->read_only);
return(trx_rollback_for_mysql_low(trx));
case TRX_STATE_PREPARED:
case TRX_STATE_PREPARED_RECOVERED:
- ut_ad(!trx_is_autocommit_non_locking(trx));
- if (trx->rsegs.m_redo.undo) {
+ ut_ad(!trx->is_autocommit_non_locking());
+ if (trx->has_logged_persistent()) {
/* The XA ROLLBACK of a XA PREPARE transaction
will consist of multiple mini-transactions.
@@ -272,7 +279,7 @@ dberr_t trx_rollback_for_mysql(trx_t* trx)
return(trx_rollback_for_mysql_low(trx));
case TRX_STATE_COMMITTED_IN_MEMORY:
- check_trx_state(trx);
+ ut_ad(!trx->is_autocommit_non_locking());
break;
}
@@ -301,7 +308,9 @@ trx_rollback_last_sql_stat_for_mysql(
return(DB_SUCCESS);
case TRX_STATE_ACTIVE:
- assert_trx_nonlocking_or_in_list(trx);
+ ut_ad(trx->mysql_thd);
+ ut_ad(!trx->is_recovered);
+ ut_ad(!trx->is_autocommit_non_locking() || trx->read_only);
trx->op_info = "rollback of SQL statement";
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index d7375f98b6f..298286899f1 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -140,7 +140,7 @@ trx_init(
trx->auto_commit = false;
- trx->will_lock = 0;
+ trx->will_lock = false;
trx->ddl = false;
@@ -345,13 +345,13 @@ trx_t *trx_create()
MEM_MAKE_DEFINED(trx, sizeof *trx);
#endif
- assert_trx_is_free(trx);
+ trx->assert_freed();
mem_heap_t* heap;
ib_alloc_t* alloc;
/* We just got trx from pool, it should be non locking */
- ut_ad(trx->will_lock == 0);
+ ut_ad(!trx->will_lock);
ut_ad(trx->state == TRX_STATE_NOT_STARTED);
ut_ad(!trx->rw_trx_hash_pins);
@@ -395,7 +395,7 @@ void trx_t::free()
dict_operation= TRX_DICT_OP_NONE;
trx_sys.deregister_trx(this);
- assert_trx_is_free(this);
+ assert_freed();
trx_sys.rw_trx_hash.put_pins(this);
mysql_thd= NULL;
@@ -567,7 +567,7 @@ void trx_disconnect_prepared(trx_t *trx)
trx->is_recovered= true;
trx->mysql_thd= NULL;
/* todo/fixme: suggest to do it at innodb prepare */
- trx->will_lock= 0;
+ trx->will_lock= false;
}
/****************************************************************//**
@@ -917,11 +917,10 @@ void trx_t::remove_flush_observer()
/** Assign a rollback segment for modifying temporary tables.
@return the assigned rollback segment */
-trx_rseg_t*
-trx_t::assign_temp_rseg()
+trx_rseg_t *trx_t::assign_temp_rseg()
{
ut_ad(!rsegs.m_noredo.rseg);
- ut_ad(!trx_is_autocommit_non_locking(this));
+ ut_ad(!is_autocommit_non_locking());
compile_time_assert(ut_is_2pow(TRX_SYS_N_RSEGS));
/* Choose a temporary rollback segment between 0 and 127
@@ -971,8 +970,8 @@ trx_start_low(
&& thd_trx_is_read_only(trx->mysql_thd));
if (!trx->auto_commit) {
- ++trx->will_lock;
- } else if (trx->will_lock == 0) {
+ trx->will_lock = true;
+ } else if (!trx->will_lock) {
trx->read_only = true;
}
@@ -1015,7 +1014,7 @@ trx_start_low(
trx_sys.register_rw(trx);
} else {
- if (!trx_is_autocommit_non_locking(trx)) {
+ if (!trx->is_autocommit_non_locking()) {
/* If this is a read-only transaction that is writing
to a temporary table then it needs a transaction id
@@ -1285,11 +1284,14 @@ trx_commit_in_memory(
trx->must_flush_log_later = false;
trx->read_view.close();
- if (trx_is_autocommit_non_locking(trx)) {
+ if (trx->is_autocommit_non_locking()) {
ut_ad(trx->id == 0);
ut_ad(trx->read_only);
+ ut_ad(!trx->will_lock);
ut_a(!trx->is_recovered);
ut_ad(trx->rsegs.m_redo.rseg == NULL);
+ ut_ad(trx->mysql_thd);
+ ut_ad(trx->state == TRX_STATE_ACTIVE);
/* Note: We are asserting without holding the lock mutex. But
that is OK because this transaction is not waiting and cannot
@@ -1305,8 +1307,6 @@ trx_commit_in_memory(
and it cannot be removed from the trx_list and freed
without first acquiring the trx_sys_t::mutex. */
- ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
-
MONITOR_INC(MONITOR_TRX_NL_RO_COMMIT);
DBUG_LOG("trx", "Autocommit in memory: " << trx);
@@ -1437,7 +1437,7 @@ trx_commit_in_memory(
trx->wsrep = false;
#endif
- assert_trx_is_free(trx);
+ trx->assert_freed();
trx_init(trx);
@@ -1452,8 +1452,6 @@ trx_commit_in_memory(
@param[in,out] mtr mini-transaction (NULL if no modifications) */
void trx_commit_low(trx_t* trx, mtr_t* mtr)
{
- assert_trx_nonlocking_or_in_list(trx);
- ut_ad(!trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY));
ut_ad(!mtr || mtr->is_active());
ut_d(bool aborted = trx->in_rollback
&& trx->error_state == DB_DEADLOCK);
@@ -1462,23 +1460,15 @@ void trx_commit_low(trx_t* trx, mtr_t* mtr)
/* undo_no is non-zero if we're doing the final commit. */
if (trx->fts_trx != NULL && trx->undo_no != 0) {
- dberr_t error;
-
- ut_a(!trx_is_autocommit_non_locking(trx));
-
- error = fts_commit(trx);
+ ut_a(!trx->is_autocommit_non_locking());
/* FTS-FIXME: Temporarily tolerate DB_DUPLICATE_KEY
instead of dying. This is a possible scenario if there
is a crash between insert to DELETED table committing
and transaction committing. The fix would be able to
return error from this function */
- if (error != DB_SUCCESS && error != DB_DUPLICATE_KEY) {
- /* FTS-FIXME: once we can return values from this
- function, we should do so and signal an error
- instead of just dying. */
-
- ut_error;
+ if (dberr_t error = fts_commit(trx)) {
+ ut_a(error == DB_DUPLICATE_KEY);
}
}
@@ -1770,7 +1760,6 @@ trx_print_low(
/*!< in: mem_heap_get_size(trx->lock.lock_heap) */
{
ibool newline;
- const char* op_info;
fprintf(f, "TRANSACTION " TRX_ID_FMT, trx_get_id_for_print(trx));
@@ -1797,9 +1786,7 @@ trx_print_low(
fprintf(f, ", state %lu", (ulong) trx->state);
ut_ad(0);
state_ok:
-
- /* prevent a race condition */
- op_info = trx->op_info;
+ const char* op_info = trx->op_info;
if (*op_info) {
putc(' ', f);
@@ -2270,7 +2257,7 @@ trx_start_internal_low(
/* Ensure it is not flagged as an auto-commit-non-locking
transaction. */
- trx->will_lock = 1;
+ trx->will_lock = true;
trx->internal = true;
@@ -2286,7 +2273,7 @@ trx_start_internal_read_only_low(
/* Ensure it is not flagged as an auto-commit-non-locking
transaction. */
- trx->will_lock = 1;
+ trx->will_lock = true;
trx->internal = true;
@@ -2307,13 +2294,7 @@ trx_start_for_ddl_low(
the data dictionary will be locked in crash recovery. */
trx_set_dict_operation(trx, op);
-
- /* Ensure it is not flagged as an auto-commit-non-locking
- transation. */
- trx->will_lock = 1;
-
trx->ddl= true;
-
trx_start_internal_low(trx);
return;
@@ -2340,7 +2321,7 @@ trx_set_rw_mode(
trx_t* trx) /*!< in/out: transaction that is RW */
{
ut_ad(trx->rsegs.m_redo.rseg == 0);
- ut_ad(!trx_is_autocommit_non_locking(trx));
+ ut_ad(!trx->is_autocommit_non_locking());
ut_ad(!trx->read_only);
ut_ad(trx->id == 0);
diff --git a/storage/oqgraph/mysql-test/oqgraph/social.test b/storage/oqgraph/mysql-test/oqgraph/social.test
index 69eb7698bb9..a71b160cc1d 100644
--- a/storage/oqgraph/mysql-test/oqgraph/social.test
+++ b/storage/oqgraph/mysql-test/oqgraph/social.test
@@ -1,3 +1,6 @@
+# The test can take very long time with valgrind
+--source include/not_valgrind.inc
+
--disable_warnings
DROP TABLE IF EXISTS rsb, rsb_graph;
--enable_warnings
diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc
index cc61aa85598..e529c530855 100644
--- a/storage/tokudb/ha_tokudb.cc
+++ b/storage/tokudb/ha_tokudb.cc
@@ -7266,7 +7266,7 @@ int ha_tokudb::create(
// in the database directory, so automatic filename-based
// discover_table_names() doesn't work either. So, it must force .frm
// file to disk.
- form->s->write_frm_image();
+ error= form->s->write_frm_image();
#endif
#if defined(TOKU_INCLUDE_OPTION_STRUCTS) && TOKU_INCLUDE_OPTION_STRUCTS
@@ -7298,8 +7298,8 @@ int ha_tokudb::create(
#endif // defined(TOKU_INCLUDE_OPTION_STRUCTS) && TOKU_INCLUDE_OPTION_STRUCTS
const toku_compression_method compression_method =
row_format_to_toku_compression_method(row_format);
-
bool create_from_engine = (create_info->table_options & HA_OPTION_CREATE_FROM_ENGINE);
+ if (error) { goto cleanup; }
if (create_from_engine) {
// table already exists, nothing to do
error = 0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/bug-23786.result b/storage/tokudb/mysql-test/tokudb/r/bug-23786.result
new file mode 100644
index 00000000000..1b21758b85a
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/r/bug-23786.result
@@ -0,0 +1,10 @@
+#
+# 10.2 Test
+#
+# MDEV-23786: Assertion `!is_set() || (m_status == DA_OK_BULK &&
+# is_bulk_op())'failed for TokuDB engine CREATE TABLE
+#
+set default_storage_engine='tokudb';
+CREATE TABLE _uppercase.t (a INT) ENGINE=TokuDB;
+ERROR 42000: Unknown database '_uppercase'
+# End of 10.2 Test
diff --git a/storage/tokudb/mysql-test/tokudb/t/bug-23786.test b/storage/tokudb/mysql-test/tokudb/t/bug-23786.test
new file mode 100644
index 00000000000..a8a0c4a1577
--- /dev/null
+++ b/storage/tokudb/mysql-test/tokudb/t/bug-23786.test
@@ -0,0 +1,14 @@
+source include/have_tokudb.inc;
+
+--echo #
+--echo # 10.2 Test
+--echo #
+--echo # MDEV-23786: Assertion `!is_set() || (m_status == DA_OK_BULK &&
+--echo # is_bulk_op())'failed for TokuDB engine CREATE TABLE
+--echo #
+
+set default_storage_engine='tokudb';
+--error ER_BAD_DB_ERROR
+CREATE TABLE _uppercase.t (a INT) ENGINE=TokuDB;
+
+--echo # End of 10.2 Test