Commit 9c5835e0 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.5 into 10.6

parents 78e023c2 18eab4a8
......@@ -10,8 +10,11 @@
.ninja_*
*.mri
*.mri.tpl
/.cproject
/.project
.gdb_history
.vs/
/.settings/
errmsg.sys
typescript
_CPack_Packages
......
......@@ -173,6 +173,10 @@ IF(DISABLE_SHARED)
SET(WITHOUT_DYNAMIC_PLUGINS 1)
ENDIF()
OPTION(ENABLED_PROFILING "Enable profiling" ON)
OPTION(ENABLED_JSON_WRITER_CONSISTENCY_CHECKS "Enable Json_writer_object / Json_writer_array checking to produce consistent JSON output" OFF)
IF(ENABLED_JSON_WRITER_CONSISTENCY_CHECKS)
ADD_DEFINITIONS(-DENABLED_JSON_WRITER_CONSISTENCY_CHECKS)
ENDIF()
OPTION(WITHOUT_SERVER "Build only the client library and clients" OFF)
IF(UNIX)
OPTION(WITH_VALGRIND "Valgrind instrumentation" OFF)
......
......@@ -11,21 +11,22 @@ MACRO(BUNDLE_PCRE2)
FOREACH(lib pcre2-posix pcre2-8)
ADD_LIBRARY(${lib} STATIC IMPORTED GLOBAL)
ADD_DEPENDENCIES(${lib} pcre2)
GET_PROPERTY(MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
IF(MULTICONFIG)
SET(intdir "${CMAKE_CFG_INTDIR}/")
ELSE()
SET(intdir)
ENDIF()
SET(file ${dir}/src/pcre2-build/${intdir}${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX})
IF(WIN32)
# Debug libary name.
# Same condition as in pcre2 CMakeLists.txt that adds "d"
GET_PROPERTY(MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
IF(MULTICONFIG)
SET(intdir "${CMAKE_CFG_INTDIR}/")
ELSE()
SET(intdir)
ENDIF()
SET(file ${dir}/src/pcre2-build/${intdir}${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX})
SET(file_d ${dir}/src/pcre2-build/${intdir}${CMAKE_STATIC_LIBRARY_PREFIX}${lib}d${CMAKE_STATIC_LIBRARY_SUFFIX})
SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LOCATION_DEBUG ${file_d})
ELSE()
SET(file ${dir}/src/pcre2-build/${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX})
SET(file_d)
ENDIF()
SET(byproducts ${byproducts} BUILD_BYPRODUCTS ${file} ${file_d})
......
......@@ -1271,6 +1271,7 @@ sub command_line_setup {
{
$path_client_bindir= mtr_path_exists("$bindir/client_release",
"$bindir/client_debug",
"$bindir/client/debug",
"$bindir/client$opt_vs_config",
"$bindir/client",
"$bindir/bin");
......
......@@ -71,35 +71,16 @@ connection node_3a;
SET SESSION wsrep_sync_wait = 0;
SET SESSION wsrep_sync_wait = DEFAULT;
connection node_1a;
Timeout in wait_condition.inc for SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
Id User Host db Command Time State Info Progress
1 system user NULL Sleep 66 wsrep aborter idle NULL 0.000
2 system user NULL Sleep 66 closing tables NULL 0.000
10 root localhost test Sleep 58 NULL 0.000
11 root localhost:52722 test Sleep 56 NULL 0.000
12 root localhost:52724 test Query 0 starting show full processlist 0.000
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
EXPECT_0
1
0
connection node_2a;
Timeout in wait_condition.inc for SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
Id User Host db Command Time State Info Progress
1 system user NULL Sleep 96 wsrep aborter idle NULL 0.000
2 system user NULL Sleep 87 closing tables NULL 0.000
10 root localhost:37222 test Sleep 64 NULL 0.000
11 root localhost:37228 test Query 0 starting show full processlist 0.000
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
EXPECT_0
1
0
connection node_3a;
Timeout in wait_condition.inc for SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
Id User Host db Command Time State Info Progress
1 system user NULL Sleep 122 wsrep aborter idle NULL 0.000
2 system user NULL Sleep 117 closing tables NULL 0.000
10 root localhost:60992 test Sleep 117 NULL 0.000
11 root localhost:60994 test Query 0 starting show full processlist 0.000
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
EXPECT_0
1
0
connection node_1;
DROP TABLE t1;
......@@ -219,4 +219,65 @@ include/sync_with_master_gtid.inc
connection master;
drop database test_ign;
drop table t1, t2, t3, tm;
#
# MDEV-26682 slave lock timeout with XA and gap locks
#
create table t1 (a int primary key, b int unique) engine=innodb;
insert t1 values (1,1),(3,3),(5,5);
connection slave;
set session tx_isolation='repeatable-read';
start transaction;
select * from t1;
a b
1 1
3 3
5 5
connect m2, localhost, root;
delete from t1 where a=3;
xa start 'x1';
update t1 set b=3 where a=5;
xa end 'x1';
xa prepare 'x1';
connect m3, localhost, root;
insert t1 values (2, 2);
-->slave
connection slave;
commit;
select * from t1;
a b
1 1
2 2
5 5
connection m2;
xa rollback 'x1';
disconnect m2;
disconnect m3;
connection master;
drop table t1;
create table t1 (id int auto_increment primary key, c1 int not null unique)
engine=innodb;
create table t2 (id int auto_increment primary key, c1 int not null,
foreign key(c1) references t1(c1), unique key(c1)) engine=innodb;
insert t1 values (869,1), (871,3), (873,4), (872,5), (870,6), (877,7);
insert t2 values (795,6), (800,7);
xa start '1';
update t2 set id = 9, c1 = 5 where c1 in (null, null, null, null, null, 7, 3);
connect con1, localhost,root;
xa start '2';
delete from t1 where c1 like '3%';
xa end '2';
xa prepare '2';
connection master;
xa end '1';
xa prepare '1';
->slave
connection slave;
connection slave;
include/sync_with_master_gtid.inc
connection con1;
xa commit '2';
disconnect con1;
connection master;
xa commit '1';
drop table t2, t1;
include/rpl_end.inc
......@@ -228,6 +228,67 @@ include/sync_with_master_gtid.inc
connection master;
drop database test_ign;
drop table t1, t2, t3, tm;
#
# MDEV-26682 slave lock timeout with XA and gap locks
#
create table t1 (a int primary key, b int unique) engine=innodb;
insert t1 values (1,1),(3,3),(5,5);
connection slave;
set session tx_isolation='repeatable-read';
start transaction;
select * from t1;
a b
1 1
3 3
5 5
connect m2, localhost, root;
delete from t1 where a=3;
xa start 'x1';
update t1 set b=3 where a=5;
xa end 'x1';
xa prepare 'x1';
connect m3, localhost, root;
insert t1 values (2, 2);
-->slave
connection slave;
commit;
select * from t1;
a b
1 1
2 2
5 5
connection m2;
xa rollback 'x1';
disconnect m2;
disconnect m3;
connection master;
drop table t1;
create table t1 (id int auto_increment primary key, c1 int not null unique)
engine=innodb;
create table t2 (id int auto_increment primary key, c1 int not null,
foreign key(c1) references t1(c1), unique key(c1)) engine=innodb;
insert t1 values (869,1), (871,3), (873,4), (872,5), (870,6), (877,7);
insert t2 values (795,6), (800,7);
xa start '1';
update t2 set id = 9, c1 = 5 where c1 in (null, null, null, null, null, 7, 3);
connect con1, localhost,root;
xa start '2';
delete from t1 where c1 like '3%';
xa end '2';
xa prepare '2';
connection master;
xa end '1';
xa prepare '1';
->slave
connection slave;
connection slave;
include/sync_with_master_gtid.inc
connection con1;
xa commit '2';
disconnect con1;
connection master;
xa commit '1';
drop table t2, t1;
connection slave;
include/stop_slave.inc
SET @@global.gtid_pos_auto_engines="";
......
#
# This "body" file checks general properties of XA transaction replication
# as of MDEV-7974.
# as of MDEV-742.
# Parameters:
# --let rpl_xa_check= SELECT ...
#
......@@ -353,3 +353,81 @@ source include/sync_with_master_gtid.inc;
connection master;
--eval drop database test_ign
drop table t1, t2, t3, tm;
--echo #
--echo # MDEV-26682 slave lock timeout with XA and gap locks
--echo #
create table t1 (a int primary key, b int unique) engine=innodb;
insert t1 values (1,1),(3,3),(5,5);
sync_slave_with_master;
# set a strong isolation level to keep the read view below.
# alternatively a long-running select can do that too even in read-committed
set session tx_isolation='repeatable-read';
start transaction;
# opens a read view to disable purge on the slave
select * from t1;
connect m2, localhost, root;
# now, delete a value, purge it on the master, but not on the slave
delete from t1 where a=3;
xa start 'x1';
# this sets a gap lock on <3>, when it exists (so, on the slave)
update t1 set b=3 where a=5;
xa end 'x1';
xa prepare 'x1';
connect m3, localhost, root;
# and this tries to insert straight into the locked gap
insert t1 values (2, 2);
echo -->slave;
sync_slave_with_master;
commit;
select * from t1;
connection m2;
xa rollback 'x1';
disconnect m2;
disconnect m3;
connection master;
drop table t1;
create table t1 (id int auto_increment primary key, c1 int not null unique)
engine=innodb;
create table t2 (id int auto_increment primary key, c1 int not null,
foreign key(c1) references t1(c1), unique key(c1)) engine=innodb;
insert t1 values (869,1), (871,3), (873,4), (872,5), (870,6), (877,7);
insert t2 values (795,6), (800,7);
xa start '1';
update t2 set id = 9, c1 = 5 where c1 in (null, null, null, null, null, 7, 3);
connect con1, localhost,root;
xa start '2';
delete from t1 where c1 like '3%';
xa end '2';
xa prepare '2';
connection master;
xa end '1';
xa prepare '1';
echo ->slave;
sync_slave_with_master;
connection slave;
source include/sync_with_master_gtid.inc;
connection con1;
xa commit '2';
disconnect con1;
connection master;
xa commit '1';
drop table t2, t1;
......@@ -88,5 +88,32 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff'
DROP TABLE t1;
#
# MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
#
CREATE TABLE t1 (pk inet6, c text) engine=myisam;
INSERT INTO t1 VALUES ('::',1);
CREATE TABLE t2 (d text, KEY (d)) engine=innodb ;
Warnings:
Note 1071 Specified key was too long; max key length is 3072 bytes
INSERT INTO t2 VALUES (2);
SELECT * FROM t2 JOIN t1 ON ( t1.pk > t2.d);
d pk c
Warnings:
Warning 1292 Incorrect inet6 value: '2'
UPDATE t2 JOIN t1 ON ( t1.pk > t2.d) SET t1.c = 1;
ERROR 22007: Incorrect inet6 value: '2'
SET sql_mode='';
UPDATE t2 JOIN t1 ON ( t1.pk > t2.d) SET t1.c = 1;
Warnings:
Warning 1292 Incorrect inet6 value: '2'
SET sql_mode=DEFAULT;
SELECT * FROM t1;
pk c
:: 1
SELECT * FROM t2;
d
2
DROP TABLE t1, t2;
#
# End of 10.5 tests
#
......@@ -12,6 +12,24 @@
SET default_storage_engine=InnoDB;
--source type_inet6_engines.inc
--echo #
--echo # MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
--echo #
CREATE TABLE t1 (pk inet6, c text) engine=myisam;
INSERT INTO t1 VALUES ('::',1);
CREATE TABLE t2 (d text, KEY (d)) engine=innodb ;
INSERT INTO t2 VALUES (2);
SELECT * FROM t2 JOIN t1 ON ( t1.pk > t2.d);
--error ER_TRUNCATED_WRONG_VALUE
UPDATE t2 JOIN t1 ON ( t1.pk > t2.d) SET t1.c = 1;
SET sql_mode='';
UPDATE t2 JOIN t1 ON ( t1.pk > t2.d) SET t1.c = 1;
SET sql_mode=DEFAULT;
SELECT * FROM t1;
SELECT * FROM t2;
DROP TABLE t1, t2;
--echo #
--echo # End of 10.5 tests
......
......@@ -88,5 +88,24 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff'
DROP TABLE t1;
#
# MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
#
CREATE TABLE t1 (c varchar(64), key(c)) engine=myisam;
INSERT INTO t1 VALUES ('0::1'),('::1'),('::2');
SELECT * FROM t1 WHERE c>CAST('::1' AS INET6);
c
::2
EXPLAIN SELECT * FROM t1 WHERE c>CAST('::1' AS INET6);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index c c 67 NULL 3 Using where; Using index
SELECT * FROM t1 WHERE c=CAST('::1' AS INET6);
c
0::1
::1
EXPLAIN SELECT * FROM t1 WHERE c=CAST('::1' AS INET6);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index c c 67 NULL 3 Using where; Using index
DROP TABLE t1;
#
# End of 10.5 tests
#
......@@ -10,6 +10,18 @@
SET default_storage_engine=MyISAM;
--source type_inet6_engines.inc
--echo #
--echo # MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
--echo #
CREATE TABLE t1 (c varchar(64), key(c)) engine=myisam;
INSERT INTO t1 VALUES ('0::1'),('::1'),('::2');
SELECT * FROM t1 WHERE c>CAST('::1' AS INET6);
EXPLAIN SELECT * FROM t1 WHERE c>CAST('::1' AS INET6);
SELECT * FROM t1 WHERE c=CAST('::1' AS INET6);
EXPLAIN SELECT * FROM t1 WHERE c=CAST('::1' AS INET6);
DROP TABLE t1;
--echo #
--echo # End of 10.5 tests
......
......@@ -1276,6 +1276,21 @@ bool Field::can_be_substituted_to_equal_item(const Context &ctx,
}
bool Field::cmp_is_done_using_type_handler_of_this(const Item_bool_func *cond,
const Item *item) const
{
/*
We could eventually take comparison_type_handler() from cond,
instead of calculating it again. But only some descendants of
Item_bool_func has this method. So this needs some hierarchy changes.
Another option is to pass "class Context" to this method.
*/
Type_handler_hybrid_field_type cmp(type_handler_for_comparison());
return !cmp.aggregate_for_comparison(item->type_handler_for_comparison()) &&
cmp.type_handler() == type_handler_for_comparison();
}
/*
This handles all numeric and BIT data types.
*/
......@@ -7368,7 +7383,7 @@ bool
Field_longstr::cmp_to_string_with_same_collation(const Item_bool_func *cond,
const Item *item) const
{
return item->cmp_type() == STRING_RESULT &&
return cmp_is_done_using_type_handler_of_this(cond, item) &&
charset() == cond->compare_collation();
}
......@@ -7377,7 +7392,7 @@ bool
Field_longstr::cmp_to_string_with_stricter_collation(const Item_bool_func *cond,
const Item *item) const
{
return item->cmp_type() == STRING_RESULT &&
return cmp_is_done_using_type_handler_of_this(cond, item) &&
(charset() == cond->compare_collation() ||
cond->compare_collation()->state & MY_CS_BINSORT);
}
......
......@@ -1651,6 +1651,8 @@ class Field: public Value_source
}
int warn_if_overflow(int op_result);
Copy_func *get_identical_copy_func() const;
bool cmp_is_done_using_type_handler_of_this(const Item_bool_func *cond,
const Item *item) const;
bool can_optimize_scalar_range(const RANGE_OPT_PARAM *param,
const KEY_PART *key_part,
const Item_bool_func *cond,
......
......@@ -260,6 +260,10 @@ void Json_writer::add_str(const String &str)
add_str(str.ptr(), str.length());
}
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
thread_local std::vector<bool> Json_writer_struct::named_items_expectation;
#endif
Json_writer_temp_disable::Json_writer_temp_disable(THD *thd_arg)
{
thd= thd_arg;
......
......@@ -15,8 +15,12 @@
#ifndef JSON_WRITER_INCLUDED
#define JSON_WRITER_INCLUDED
#include "my_base.h"
#include "sql_select.h"
#include <vector>
class Opt_trace_stmt;
class Opt_trace_context;
class Json_writer;
......@@ -308,6 +312,9 @@ class Json_value_helper
/* A common base for Json_writer_object and Json_writer_array */
class Json_writer_struct
{
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
static thread_local std::vector<bool> named_items_expectation;
#endif
protected:
Json_writer* my_writer;
Json_value_helper context;
......@@ -317,16 +324,35 @@ class Json_writer_struct
bool closed;
public:
explicit Json_writer_struct(THD *thd)
explicit Json_writer_struct(THD *thd, bool expect_named_children)
{
my_writer= thd->opt_trace.get_current_json();
context.init(my_writer);
closed= false;
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
named_items_expectation.push_back(expect_named_children);
#endif
}
virtual ~Json_writer_struct()
{
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
named_items_expectation.pop_back();
#endif
}
bool trace_started()
bool trace_started() const
{
return my_writer != 0;
}
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
bool named_item_expected() const
{
return named_items_expectation.size() > 1
&& *(named_items_expectation.rbegin() + 1);
}
#endif
};
......@@ -347,15 +373,21 @@ class Json_writer_object : public Json_writer_struct
}
public:
explicit Json_writer_object(THD *thd)
: Json_writer_struct(thd)
: Json_writer_struct(thd, true)
{
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
DBUG_ASSERT(!named_item_expected());
#endif
if (unlikely(my_writer))
my_writer->start_object();
}
explicit Json_writer_object(THD* thd, const char *str)
: Json_writer_struct(thd)
: Json_writer_struct(thd, true)
{
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
DBUG_ASSERT(named_item_expected());
#endif
if (unlikely(my_writer))
my_writer->add_member(str).start_object();
}
......@@ -519,14 +551,22 @@ class Json_writer_object : public Json_writer_struct
class Json_writer_array : public Json_writer_struct
{
public:
Json_writer_array(THD *thd): Json_writer_struct(thd)
Json_writer_array(THD *thd)
: Json_writer_struct(thd, false)
{
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
DBUG_ASSERT(!named_item_expected());
#endif
if (unlikely(my_writer))
my_writer->start_array();
}
Json_writer_array(THD *thd, const char *str) : Json_writer_struct(thd)
Json_writer_array(THD *thd, const char *str)
: Json_writer_struct(thd, false)
{
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
DBUG_ASSERT(named_item_expected());
#endif
if (unlikely(my_writer))
my_writer->add_member(str).start_array();
}
......
......@@ -427,6 +427,10 @@ lock_rec_unlock(
and release possible other transactions waiting because of these locks. */
void lock_release(trx_t* trx);
/** Release non-exclusive locks on XA PREPARE,
and release possible other transactions waiting because of these locks. */
void lock_release_on_prepare(trx_t *trx);
/** Release locks on a table whose creation is being rolled back */
ATTRIBUTE_COLD void lock_release_on_rollback(trx_t *trx, dict_table_t *table);
......
......@@ -3883,6 +3883,124 @@ void lock_release(trx_t *trx)
#endif
}
/** Release non-exclusive locks on XA PREPARE,
and wake up possible other transactions waiting because of these locks.
@param trx transaction in XA PREPARE state
@return whether all locks were released */
static bool lock_release_on_prepare_try(trx_t *trx)
{
/* At this point, trx->lock.trx_locks can still be modified by other
threads to convert implicit exclusive locks into explicit ones.
The function lock_table_create() should never be invoked on behalf
of a transaction that is running in another thread. Also there, we
will assert that the current transaction be active. */
DBUG_ASSERT(trx->state == TRX_STATE_PREPARED);
bool all_released= true;
lock_sys.rd_lock(SRW_LOCK_CALL);
trx->mutex_lock();
/* Note: Normally, trx->mutex is not held while acquiring
a lock table latch, but here we are following the opposite order.
To avoid deadlocks, we only try to acquire the lock table latches
but not keep waiting for them. */
for (lock_t *prev, *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock;
lock= prev)
{
ut_ad(lock->trx == trx);
prev= UT_LIST_GET_PREV(trx_locks, lock);
if (!lock->is_table())
{
ut_ad(!lock->index->table->is_temporary());
if (lock->mode() == LOCK_X && !lock->is_gap())
continue;
auto &lock_hash= lock_sys.hash_get(lock->type_mode);
auto cell= lock_hash.cell_get(lock->un_member.rec_lock.page_id.fold());
auto latch= lock_sys_t::hash_table::latch(cell);
if (latch->try_acquire())
{
lock_rec_dequeue_from_page(lock, false);
latch->release();
}
else
all_released= false;
}
else
{
dict_table_t *table= lock->un_member.tab_lock.table;
ut_ad(!table->is_temporary());
switch (lock->mode()) {
case LOCK_IS:
case LOCK_S:
if (table->lock_mutex_trylock())
{
lock_table_dequeue(lock, false);
table->lock_mutex_unlock();
}
else
all_released= false;
break;
case LOCK_IX:
case LOCK_X:
ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation);
/* fall through */
default:
break;
}
}
}
lock_sys.rd_unlock();
trx->mutex_unlock();
return all_released;
}
/** Release non-exclusive locks on XA PREPARE,
and release possible other transactions waiting because of these locks. */
void lock_release_on_prepare(trx_t *trx)
{
for (ulint count= 5; count--; )
if (lock_release_on_prepare_try(trx))
return;
LockMutexGuard g{SRW_LOCK_CALL};
trx->mutex_lock();
for (lock_t *prev, *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock;
lock= prev)
{
ut_ad(lock->trx == trx);
prev= UT_LIST_GET_PREV(trx_locks, lock);
if (!lock->is_table())
{
ut_ad(!lock->index->table->is_temporary());
if (lock->mode() != LOCK_X || lock->is_gap())
lock_rec_dequeue_from_page(lock, false);
}
else
{
dict_table_t *table= lock->un_member.tab_lock.table;
ut_ad(!table->is_temporary());
switch (lock->mode()) {
case LOCK_IS:
case LOCK_S:
lock_table_dequeue(lock, false);
break;
case LOCK_IX:
case LOCK_X:
ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation);
/* fall through */
default:
break;
}
}
}
trx->mutex_unlock();
}
/** Release locks on a table whose creation is being rolled back */
ATTRIBUTE_COLD void lock_release_on_rollback(trx_t *trx, dict_table_t *table)
{
......
......@@ -1868,6 +1868,20 @@ trx_prepare(
We must not be holding any mutexes or latches here. */
trx_flush_log_if_needed(lsn, trx);
if (!UT_LIST_GET_LEN(trx->lock.trx_locks)
|| trx->isolation_level == TRX_ISO_SERIALIZABLE) {
/* Do not release any locks at the
SERIALIZABLE isolation level. */
} else if (!trx->mysql_thd
|| thd_sql_command(trx->mysql_thd)
!= SQLCOM_XA_PREPARE) {
/* Do not release locks for XA COMMIT ONE PHASE
or for internal distributed transactions
(XID::get_my_xid() would be nonzero). */
} else {
lock_release_on_prepare(trx);
}
}
}
......
for master_1
for child2
child2_1
child2_2
child2_3
for child3
#
# MDEV-26539 SIGSEGV in spider_check_and_set_trx_isolation and I_P_List_iterator from THD::drop_temporary_table (10.5.3 opt only) on ALTER
#
connection child2_1;
CREATE DATABASE auto_test_remote;
USE auto_test_remote;
CREATE TABLE tbl_a (
c INT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
connection master_1;
CREATE DATABASE auto_test_local;
USE auto_test_local;
CREATE TABLE tbl_a (
c INT
) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='table "tbl_a"' PARTITION BY LIST COLUMNS (c) (
PARTITION pt1 DEFAULT COMMENT = 'srv "s_2_1"'
);
INSERT INTO tbl_a VALUES (1);
ALTER TABLE tbl_a CHECK PARTITION ALL;
Table Op Msg_type Msg_text
auto_test_local.tbl_a check status OK
DROP DATABASE auto_test_local;
connection child2_1;
DROP DATABASE auto_test_remote;
for master_1
for child2
child2_1
child2_2
child2_3
for child3
!include include/default_mysqld.cnf
!include ../my_1_1.cnf
!include ../my_2_1.cnf
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
--echo #
--echo # MDEV-26539 SIGSEGV in spider_check_and_set_trx_isolation and I_P_List_iterator from THD::drop_temporary_table (10.5.3 opt only) on ALTER
--echo #
--connection child2_1
CREATE DATABASE auto_test_remote;
USE auto_test_remote;
eval CREATE TABLE tbl_a (
c INT
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
--connection master_1
CREATE DATABASE auto_test_local;
USE auto_test_local;
eval CREATE TABLE tbl_a (
c INT
) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='table "tbl_a"' PARTITION BY LIST COLUMNS (c) (
PARTITION pt1 DEFAULT COMMENT = 'srv "s_2_1"'
);
INSERT INTO tbl_a VALUES (1);
ALTER TABLE tbl_a CHECK PARTITION ALL;
DROP DATABASE auto_test_local;
--connection child2_1
DROP DATABASE auto_test_remote;
--disable_query_log
--disable_result_log
--source ../../t/test_deinit.inc
--enable_result_log
--enable_query_log
......@@ -3802,10 +3802,8 @@ int spider_check_trx_and_get_conn(
}
spider->wide_handler->trx = trx;
spider->set_error_mode();
if (
spider->wide_handler->sql_command != SQLCOM_DROP_TABLE &&
spider->wide_handler->sql_command != SQLCOM_ALTER_TABLE
) {
if (spider->wide_handler->sql_command != SQLCOM_DROP_TABLE)
{
SPIDER_TRX_HA *trx_ha = spider_check_trx_ha(trx, spider);
if (!trx_ha || trx_ha->wait_for_reusing)
spider_trx_set_link_idx_for_all(spider);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment