mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Merge 10.2 into 10.3
This commit is contained in:
commit
f50eb0d398
35 changed files with 402 additions and 268 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
#
|
||||
#
|
||||
|
|
|
@ -2919,6 +2919,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 #
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
52
mysql-test/suite/galera/r/galera_fk_lock_wait.result
Normal file
52
mysql-test/suite/galera/r/galera_fk_lock_wait.result
Normal file
|
@ -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;
|
40
mysql-test/suite/galera/t/galera_fk_lock_wait.test
Normal file
40
mysql-test/suite/galera/t/galera_fk_lock_wait.test
Normal file
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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()
|
||||
*/
|
||||
};
|
||||
|
||||
|
|
|
@ -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) ||
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
10
storage/tokudb/mysql-test/tokudb/r/bug-23786.result
Normal file
10
storage/tokudb/mysql-test/tokudb/r/bug-23786.result
Normal file
|
@ -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
|
14
storage/tokudb/mysql-test/tokudb/t/bug-23786.test
Normal file
14
storage/tokudb/mysql-test/tokudb/t/bug-23786.test
Normal file
|
@ -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
|
Loading…
Add table
Reference in a new issue