diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-07-27 10:47:17 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-07-27 10:47:17 +0300 |
commit | f50eb0d398f5f5eb2110192be436e70acd44cb9d (patch) | |
tree | 10474699ef727691212dda1cd07fb224c1198770 | |
parent | 2575eaa502b4253181651decfda46beef7f3f026 (diff) | |
parent | afe00bb7cce7de279e48a83ededc71b3f8cfafcf (diff) | |
download | mariadb-git-f50eb0d398f5f5eb2110192be436e70acd44cb9d.tar.gz |
Merge 10.2 into 10.3
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 |