summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2020-05-15 17:13:35 +0300
committerAleksey Midenkov <midenok@gmail.com>2020-05-15 17:13:35 +0300
commitf2a944516ea8fd3de1d79d46da5aa1c8a32cd78d (patch)
treea58d318446f4ac7fc199e53efa7e0029023cc3c6
parent3b251e24b6c8fe81bc5eeca086d9c1e57e6739d2 (diff)
parenta4996f951d731322acc63033646d950ddbb0f60c (diff)
downloadmariadb-git-f2a944516ea8fd3de1d79d46da5aa1c8a32cd78d.tar.gz
Merge 10.4 into 10.5
-rw-r--r--mysql-test/main/alter_table.result41
-rw-r--r--mysql-test/main/alter_table.test42
-rw-r--r--mysql-test/suite/galera/r/galera_bf_kill.result72
-rw-r--r--mysql-test/suite/galera/r/galera_bf_lock_wait.result4
-rw-r--r--mysql-test/suite/galera/t/galera_bf_kill.cnf7
-rw-r--r--mysql-test/suite/galera/t/galera_bf_kill.test143
-rw-r--r--mysql-test/suite/galera/t/galera_bf_lock_wait.cnf7
-rw-r--r--mysql-test/suite/galera/t/galera_bf_lock_wait.test8
-rw-r--r--sql/field.cc2
-rw-r--r--sql/item.h5
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/service_wsrep.cc10
-rw-r--r--storage/innobase/handler/ha_innodb.cc139
-rw-r--r--storage/innobase/include/ha_prototypes.h4
-rw-r--r--storage/innobase/include/trx0trx.h46
-rw-r--r--storage/innobase/lock/lock0lock.cc2
-rw-r--r--storage/innobase/trx/trx0roll.cc3
-rw-r--r--storage/innobase/trx/trx0trx.cc13
18 files changed, 453 insertions, 97 deletions
diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result
index b012fdde54b..5999f2c43c3 100644
--- a/mysql-test/main/alter_table.result
+++ b/mysql-test/main/alter_table.result
@@ -2564,6 +2564,44 @@ drop view v1;
# End of 10.3 tests
#
#
+# MDEV-22563 Segfault on duplicate free of Item_func_in::array
+#
+create or replace table person_principal (
+person_id bigint not null,
+insurant_id varchar(10) not null,
+principal_id bigint not null,
+principal_officer_id bigint not null,
+nursing_degree tinyint null,
+nursing_degree_valid_from date not null default cast(current_timestamp(6) as date),
+carma_user_id bigint not null,
+current_date_time timestamp(6) not null default current_timestamp(6) on update current_timestamp(6),
+constraint pk_person_principal primary key (person_id asc),
+constraint ck_person_principal_nursing_degree check (nursing_degree in (1,2,3,4,5)));
+Warnings:
+Warning 1280 Name 'pk_person_principal' ignored for PRIMARY key.
+create or replace table person_principal_hist (
+person_id bigint not null,
+insurant_id varchar(10) not null,
+principal_id bigint not null,
+principal_officer_id bigint not null,
+nursing_degree tinyint null,
+nursing_degree_valid_from date not null default cast(now() as date),
+carma_user_id bigint not null,
+orig_date_time datetime(6) not null,
+constraint pk_person_principal_hist primary key (person_id asc, orig_date_time asc),
+constraint ck_person_principal_hist_nursing_degree check (nursing_degree in (1,2,3,4,5)));
+Warnings:
+Warning 1280 Name 'pk_person_principal_hist' ignored for PRIMARY key.
+insert into person_principal (person_id, insurant_id, principal_id, principal_officer_id, nursing_degree, nursing_degree_valid_from, carma_user_id)
+values (1, 'A123456789', 5, 1, 1, '2018-05-06', 1);
+alter table person_principal add column if not exists date_mask tinyint null;
+update person_principal set date_mask = 0;
+alter table person_principal modify column date_mask tinyint not null;
+drop tables person_principal_hist, person_principal;
+#
+# End of 10.4 tests
+#
+#
# MDEV-16290 ALTER TABLE ... RENAME COLUMN syntax
#
SET @save_default_engine= @@DEFAULT_STORAGE_ENGINE;
@@ -3250,9 +3288,6 @@ i2 b
PRIMARY a
drop table t1;
#
-# End of 10.5 tests
-#
-#
# ALTER TABLE IF EXISTS
#
create table t1 (a int);
diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test
index 01ab0f99d45..8b794fcfc3e 100644
--- a/mysql-test/main/alter_table.test
+++ b/mysql-test/main/alter_table.test
@@ -2078,6 +2078,44 @@ drop view v1;
--echo #
--echo #
+--echo # MDEV-22563 Segfault on duplicate free of Item_func_in::array
+--echo #
+create or replace table person_principal (
+ person_id bigint not null,
+ insurant_id varchar(10) not null,
+ principal_id bigint not null,
+ principal_officer_id bigint not null,
+ nursing_degree tinyint null,
+ nursing_degree_valid_from date not null default cast(current_timestamp(6) as date),
+ carma_user_id bigint not null,
+ current_date_time timestamp(6) not null default current_timestamp(6) on update current_timestamp(6),
+ constraint pk_person_principal primary key (person_id asc),
+ constraint ck_person_principal_nursing_degree check (nursing_degree in (1,2,3,4,5)));
+
+create or replace table person_principal_hist (
+ person_id bigint not null,
+ insurant_id varchar(10) not null,
+ principal_id bigint not null,
+ principal_officer_id bigint not null,
+ nursing_degree tinyint null,
+ nursing_degree_valid_from date not null default cast(now() as date),
+ carma_user_id bigint not null,
+ orig_date_time datetime(6) not null,
+ constraint pk_person_principal_hist primary key (person_id asc, orig_date_time asc),
+ constraint ck_person_principal_hist_nursing_degree check (nursing_degree in (1,2,3,4,5)));
+
+insert into person_principal (person_id, insurant_id, principal_id, principal_officer_id, nursing_degree, nursing_degree_valid_from, carma_user_id)
+values (1, 'A123456789', 5, 1, 1, '2018-05-06', 1);
+alter table person_principal add column if not exists date_mask tinyint null;
+update person_principal set date_mask = 0;
+alter table person_principal modify column date_mask tinyint not null;
+drop tables person_principal_hist, person_principal;
+
+--echo #
+--echo # End of 10.4 tests
+--echo #
+
+--echo #
--echo # MDEV-16290 ALTER TABLE ... RENAME COLUMN syntax
--echo #
SET @save_default_engine= @@DEFAULT_STORAGE_ENGINE;
@@ -2458,10 +2496,6 @@ order by k, c;
drop table t1;
--echo #
---echo # End of 10.5 tests
---echo #
-
---echo #
--echo # ALTER TABLE IF EXISTS
--echo #
diff --git a/mysql-test/suite/galera/r/galera_bf_kill.result b/mysql-test/suite/galera/r/galera_bf_kill.result
new file mode 100644
index 00000000000..8b620323e35
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_bf_kill.result
@@ -0,0 +1,72 @@
+connection node_2;
+connection node_1;
+connection node_2;
+CREATE TABLE t1(a int not null primary key auto_increment,b int) engine=InnoDB;
+insert into t1 values (NULL,1);
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+begin;
+update t1 set a = 5;
+connection node_2;
+select * from t1;
+a b
+2 1
+disconnect node_2a;
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+begin;
+update t1 set a =5;
+connection node_2;
+select * from t1;
+a b
+2 1
+disconnect node_2a;
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+begin;
+update t1 set a =5, b=2;
+connection node_2;
+ALTER TABLE t1 ADD UNIQUE KEY b1(b);
+ALTER TABLE t1 DROP KEY b1;
+select * from t1;
+a b
+2 1
+disconnect node_2a;
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+begin;
+update t1 set a =5, b=2;
+connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2b;
+begin;
+update t1 set a =6, b=7;
+connection node_2;
+ALTER TABLE t1 ADD UNIQUE KEY b2(b);
+ALTER TABLE t1 DROP KEY b2;
+select * from t1;
+a b
+2 1
+disconnect node_2a;
+disconnect node_2b;
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+SET SESSION wsrep_on=OFF;
+begin;
+update t1 set a =5, b=2;
+connection node_2;
+ALTER TABLE t1 ADD UNIQUE KEY b3(b);
+select * from t1;
+a b
+2 1
+disconnect node_2a;
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+SET SESSION wsrep_on=OFF;
+begin;
+update t1 set a =5, b=2;
+connection node_2;
+select * from t1;
+a b
+2 1
+disconnect node_2a;
+drop table t1;
diff --git a/mysql-test/suite/galera/r/galera_bf_lock_wait.result b/mysql-test/suite/galera/r/galera_bf_lock_wait.result
index f893848a72d..71627d11a4e 100644
--- a/mysql-test/suite/galera/r/galera_bf_lock_wait.result
+++ b/mysql-test/suite/galera/r/galera_bf_lock_wait.result
@@ -1,5 +1,7 @@
connection node_2;
connection node_1;
+connection node_1;
+call mtr.add_suppression("WSREP: Trying to continue unpaused monitor");
CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2;
ALTER TABLE t1 add primary key(a);
CREATE PROCEDURE p1()
@@ -19,7 +21,7 @@ connect node_2_p1, 127.0.0.1, root, , test, $NODE_MYPORT_2;
call p1;
connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2;
call p1;
-connection default;
+connection node_1;
checking error log for 'BF lock wait long' message for 10 times every 10 seconds ...
drop table t1;
drop procedure p1;
diff --git a/mysql-test/suite/galera/t/galera_bf_kill.cnf b/mysql-test/suite/galera/t/galera_bf_kill.cnf
new file mode 100644
index 00000000000..e68f891792c
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_kill.cnf
@@ -0,0 +1,7 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep-debug=SERVER
+
+[mysqld.2]
+wsrep-debug=SERVER
diff --git a/mysql-test/suite/galera/t/galera_bf_kill.test b/mysql-test/suite/galera/t/galera_bf_kill.test
new file mode 100644
index 00000000000..0748b732ead
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_kill.test
@@ -0,0 +1,143 @@
+--source include/galera_cluster.inc
+
+#
+# Test case 1: Start a transaction on node_2a and kill it
+# from other connection on same node
+#
+
+--connection node_2
+CREATE TABLE t1(a int not null primary key auto_increment,b int) engine=InnoDB;
+insert into t1 values (NULL,1);
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+begin;
+update t1 set a = 5;
+
+--connection node_2
+
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1
+--source include/wait_condition.inc
+
+--let $k_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1`
+
+--disable_query_log
+--eval KILL $k_thread
+--enable_query_log
+
+select * from t1;
+--disconnect node_2a
+
+#
+# Test case 2: Start a transaction on node_2a and use
+# kill query from other connection on same node
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+begin;
+update t1 set a =5;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1
+--source include/wait_condition.inc
+
+--let $k_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1`
+
+--disable_query_log
+--eval KILL QUERY $k_thread
+--enable_query_log
+
+select * from t1;
+--disconnect node_2a
+#
+# Test case 3: Start a transaction on node_2a and start a DDL on other transaction
+# that will then abort node_2a transaction
+#
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+begin;
+update t1 set a =5, b=2;
+
+--connection node_2
+ALTER TABLE t1 ADD UNIQUE KEY b1(b);
+ALTER TABLE t1 DROP KEY b1;
+
+select * from t1;
+
+--disconnect node_2a
+
+#
+# Test case 4: Start a transaction on node_2a and conflicting transaction on node_2b
+# and start a DDL on other transaction that will then abort node_2a and node_2b
+# transactions
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+begin;
+update t1 set a =5, b=2;
+
+--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2b
+begin;
+send update t1 set a =6, b=7;
+
+--connection node_2
+ALTER TABLE t1 ADD UNIQUE KEY b2(b);
+ALTER TABLE t1 DROP KEY b2;
+
+select * from t1;
+
+--disconnect node_2a
+--disconnect node_2b
+
+#
+# Test case 5: Start a transaction on node_2a with wsrep disabled
+# and start a DDL on other transaction that will then abort node_2a
+# transactions
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET SESSION wsrep_on=OFF;
+begin;
+update t1 set a =5, b=2;
+
+--connection node_2
+ALTER TABLE t1 ADD UNIQUE KEY b3(b);
+
+select * from t1;
+
+--disconnect node_2a
+
+#
+# Test case 6: Start a transaction on node_2a with wsrep disabled
+# and kill it from other connection on same node
+#
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET SESSION wsrep_on=OFF;
+begin;
+update t1 set a =5, b=2;
+
+--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1
+--source include/wait_condition.inc
+
+--let $k_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'root' AND COMMAND = 'Sleep' LIMIT 1`
+
+--disable_query_log
+--eval KILL $k_thread
+--enable_query_log
+
+
+select * from t1;
+
+--disconnect node_2a
+
+drop table t1;
+
+
+
diff --git a/mysql-test/suite/galera/t/galera_bf_lock_wait.cnf b/mysql-test/suite/galera/t/galera_bf_lock_wait.cnf
new file mode 100644
index 00000000000..e68f891792c
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_bf_lock_wait.cnf
@@ -0,0 +1,7 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep-debug=SERVER
+
+[mysqld.2]
+wsrep-debug=SERVER
diff --git a/mysql-test/suite/galera/t/galera_bf_lock_wait.test b/mysql-test/suite/galera/t/galera_bf_lock_wait.test
index e3a9077a888..a3903fd10c0 100644
--- a/mysql-test/suite/galera/t/galera_bf_lock_wait.test
+++ b/mysql-test/suite/galera/t/galera_bf_lock_wait.test
@@ -1,6 +1,10 @@
--source include/galera_cluster.inc
--source include/big_test.inc
-
+
+--connection node_1
+
+call mtr.add_suppression("WSREP: Trying to continue unpaused monitor");
+
CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2;
ALTER TABLE t1 add primary key(a);
@@ -28,7 +32,7 @@ send call p1;
--connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2
send call p1;
-connection default;
+connection node_1;
let $counter=10;
let $sleep_period=10;
diff --git a/sql/field.cc b/sql/field.cc
index 04c45dfb546..6234de43ec8 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -11086,7 +11086,7 @@ Virtual_column_info* Virtual_column_info::clone(THD *thd)
return NULL;
if (expr)
{
- dst->expr= expr->get_copy(thd);
+ dst->expr= expr->build_clone(thd);
if (!dst->expr)
return NULL;
}
diff --git a/sql/item.h b/sql/item.h
index 3073a4d240d..c5fd5d074f6 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1602,6 +1602,7 @@ public:
virtual bool is_order_clause_position() const { return false; }
/* cloning of constant items (0 if it is not const) */
virtual Item *clone_item(THD *thd) { return 0; }
+ /* deep copy item */
virtual Item* build_clone(THD *thd) { return get_copy(thd); }
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
@@ -2094,6 +2095,10 @@ public:
*/
virtual bool find_not_null_fields(table_map allowed) { return false; }
+ /*
+ Does not guarantee deep copy (depends on copy ctor).
+ See build_clone() for deep copy.
+ */
virtual Item *get_copy(THD *thd)=0;
bool cache_const_expr_analyzer(uchar **arg);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index be907a0c4b3..ab0040c9f7e 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2730,6 +2730,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
param.imerge_cost_buff_size= 0;
param.using_real_indexes= TRUE;
param.remove_jump_scans= TRUE;
+ param.max_key_parts= 0;
param.remove_false_where_parts= remove_false_parts_of_where;
param.force_default_mrr= ordered_output;
param.possible_keys.clear_all();
@@ -3451,6 +3452,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
param.using_real_indexes= FALSE;
param.real_keynr[0]= 0;
param.alloced_sel_args= 0;
+ param.max_key_parts= 0;
thd->no_errors=1;
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
index 013ec65d3f5..ce18410d9af 100644
--- a/sql/service_wsrep.cc
+++ b/sql/service_wsrep.cc
@@ -206,7 +206,15 @@ extern "C" my_bool wsrep_thd_bf_abort(THD *bf_thd, THD *victim_thd,
as RSU has paused the provider.
*/
if ((ret || !wsrep_on(victim_thd)) && signal)
- victim_thd->awake(KILL_QUERY);
+ {
+ mysql_mutex_assert_not_owner(&victim_thd->LOCK_thd_data);
+ mysql_mutex_assert_not_owner(&victim_thd->LOCK_thd_kill);
+ mysql_mutex_lock(&victim_thd->LOCK_thd_data);
+ mysql_mutex_lock(&victim_thd->LOCK_thd_kill);
+ victim_thd->awake_no_mutex(KILL_QUERY);
+ mysql_mutex_unlock(&victim_thd->LOCK_thd_kill);
+ mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
+ }
return ret;
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 8448d9291ff..98ea873a9d6 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -18907,86 +18907,129 @@ wsrep_abort_slave_trx(
(long long)bf_seqno, (long long)victim_seqno);
abort();
}
+
/*******************************************************************//**
This function is used to kill one transaction in BF. */
+
+/** This function is used to kill one transaction.
+
+This transaction was open on this node (not-yet-committed), and a
+conflicting writeset from some other node that was being applied
+caused a locking conflict. First committed (from other node)
+wins, thus open transaction is rolled back. BF stands for
+brute-force: any transaction can get aborted by galera any time
+it is necessary.
+
+This conflict can happen only when the replicated writeset (from
+other node) is being applied, not when it’s waiting in the queue.
+If our local transaction reached its COMMIT and this conflicting
+writeset was in the queue, then it should fail the local
+certification test instead.
+
+A brute force abort is only triggered by a locking conflict
+between a writeset being applied by an applier thread (slave thread)
+and an open transaction on the node, not by a Galera writeset
+comparison as in the local certification failure.
+
+@param[in] bf_thd Brute force (BF) thread
+@param[in,out] victim_trx Vimtim trx to be killed
+@param[in] signal Should victim be signaled */
+UNIV_INTERN
int
-wsrep_innobase_kill_one_trx(THD *bf_thd_ptr, const trx_t *bf_trx,
- trx_t *victim_trx, bool signal)
+wsrep_innobase_kill_one_trx(THD* bf_thd, trx_t *victim_trx,
+ bool signal)
{
- ut_ad(lock_mutex_own());
- ut_ad(trx_mutex_own(victim_trx));
- ut_ad(bf_thd_ptr);
- ut_ad(victim_trx);
+ ut_ad(bf_thd);
+ ut_ad(victim_trx);
+ ut_ad(lock_mutex_own());
+ ut_ad(trx_mutex_own(victim_trx));
DBUG_ENTER("wsrep_innobase_kill_one_trx");
- THD *bf_thd = bf_thd_ptr ? (THD*) bf_thd_ptr : NULL;
- THD *thd = (THD *) victim_trx->mysql_thd;
- int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0;
- if (!thd) {
- DBUG_PRINT("wsrep", ("no thd for conflicting lock"));
- WSREP_WARN("no THD for trx: " TRX_ID_FMT, victim_trx->id);
- DBUG_RETURN(1);
- }
+ THD *thd= (THD *) victim_trx->mysql_thd;
+ ut_ad(thd);
+ /* Note that bf_trx might not exist here e.g. on MDL conflict
+ case (test: galera_concurrent_ctas). Similarly, BF thread
+ could be also acquiring MDL-lock causing victim to be
+ aborted. However, we have not yet called innobase_trx_init()
+ for BF transaction (test: galera_many_columns)*/
+ trx_t* bf_trx= thd_to_trx(bf_thd);
+ DBUG_ASSERT(wsrep_on(bf_thd));
- if (!bf_thd) {
- DBUG_PRINT("wsrep", ("no BF thd for conflicting lock"));
- WSREP_WARN("no BF THD for trx: " TRX_ID_FMT,
- bf_trx ? bf_trx->id : 0);
- DBUG_RETURN(1);
- }
- WSREP_LOG_CONFLICT(bf_thd, thd, TRUE);
wsrep_thd_LOCK(thd);
- WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF
- "), victim: (%lu) trx: " TRX_ID_FMT,
- signal, bf_seqno,
- thd_get_thread_id(thd),
- victim_trx->id);
-
- WSREP_DEBUG("Aborting query: %s conf %s trx: %lld",
- (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void",
- wsrep_thd_transaction_state_str(thd),
- wsrep_thd_transaction_id(thd));
-
- /*
- * we mark with was_chosen_as_deadlock_victim transaction,
- * which is already marked as BF victim
- * lock_sys is held until this vicitm has aborted
- */
- victim_trx->lock.was_chosen_as_wsrep_victim = TRUE;
+ WSREP_LOG_CONFLICT(bf_thd, thd, TRUE);
+
+ WSREP_DEBUG("Aborter %s trx_id: " TRX_ID_FMT " thread: %ld "
+ "seqno: %lld client_state: %s client_mode: %s transaction_mode: %s "
+ "query: %s",
+ wsrep_thd_is_BF(bf_thd, false) ? "BF" : "normal",
+ bf_trx ? bf_trx->id : TRX_ID_MAX,
+ thd_get_thread_id(bf_thd),
+ wsrep_thd_trx_seqno(bf_thd),
+ wsrep_thd_client_state_str(bf_thd),
+ wsrep_thd_client_mode_str(bf_thd),
+ wsrep_thd_transaction_state_str(bf_thd),
+ wsrep_thd_query(bf_thd));
+
+ WSREP_DEBUG("Victim %s trx_id: " TRX_ID_FMT " thread: %ld "
+ "seqno: %lld client_state: %s client_mode: %s transaction_mode: %s "
+ "query: %s",
+ wsrep_thd_is_BF(thd, false) ? "BF" : "normal",
+ victim_trx->id,
+ thd_get_thread_id(thd),
+ wsrep_thd_trx_seqno(thd),
+ wsrep_thd_client_state_str(thd),
+ wsrep_thd_client_mode_str(thd),
+ wsrep_thd_transaction_state_str(thd),
+ wsrep_thd_query(thd));
+
+ /* Mark transaction as a victim for Galera abort */
+ victim_trx->lock.was_chosen_as_wsrep_victim= true;
+
+ /* Note that we need to release this as it will be acquired
+ below in wsrep-lib */
wsrep_thd_UNLOCK(thd);
+
if (wsrep_thd_bf_abort(bf_thd, thd, signal))
{
- if (victim_trx->lock.wait_lock) {
+ lock_t* wait_lock = victim_trx->lock.wait_lock;
+ if (wait_lock) {
+ DBUG_ASSERT(victim_trx->is_wsrep());
WSREP_DEBUG("victim has wait flag: %lu",
thd_get_thread_id(thd));
- lock_t* wait_lock = victim_trx->lock.wait_lock;
- if (wait_lock) {
- WSREP_DEBUG("canceling wait lock");
- victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
- lock_cancel_waiting_and_release(wait_lock);
- }
+ WSREP_DEBUG("canceling wait lock");
+ victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
+ lock_cancel_waiting_and_release(wait_lock);
}
}
DBUG_RETURN(0);
}
+/** This function forces the victim transaction to abort. Aborting the
+ transaction does NOT end it, it still has to be rolled back.
+
+ @param bf_thd brute force THD asking for the abort
+ @param victim_thd victim THD to be aborted
+
+ @return 0 victim was aborted
+ @return -1 victim thread was aborted (no transaction)
+*/
static
int
wsrep_abort_transaction(
-/*====================*/
handlerton*,
THD *bf_thd,
THD *victim_thd,
my_bool signal)
{
DBUG_ENTER("wsrep_innobase_abort_thd");
+ ut_ad(bf_thd);
+ ut_ad(victim_thd);
trx_t* victim_trx = thd_to_trx(victim_thd);
- trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL;
WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %s",
wsrep_thd_query(bf_thd),
@@ -18996,7 +19039,7 @@ wsrep_abort_transaction(
if (victim_trx) {
lock_mutex_enter();
trx_mutex_enter(victim_trx);
- int rcode= wsrep_innobase_kill_one_trx(bf_thd, bf_trx,
+ int rcode= wsrep_innobase_kill_one_trx(bf_thd,
victim_trx, signal);
trx_mutex_exit(victim_trx);
lock_mutex_exit();
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index f84540cacc8..ef1174c95dd 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -230,8 +230,8 @@ innobase_casedn_str(
#ifdef WITH_WSREP
int
-wsrep_innobase_kill_one_trx(THD *bf_thd, const trx_t *bf_trx,
- trx_t *victim_trx, bool signal);
+wsrep_innobase_kill_one_trx(THD *bf_thd, trx_t *victim_trx,
+ bool signal);
ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, ulint str_length,
unsigned int buf_length);
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index be4504f71d8..294670a6f43 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -435,32 +435,6 @@ Check transaction state */
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(UT_LIST_GET_LEN((t)->lock.evicted_tables) == 0); \
- ut_ad((t)->dict_operation == TRX_DICT_OP_NONE); \
-} while(0)
-
-/** Check if transaction is in-active so that it can be freed and put back to
-transaction pool.
-@param t transaction handle */
-#define assert_trx_is_inactive(t) do { \
- assert_trx_is_free((t)); \
- ut_ad((t)->dict_operation_lock_mode == 0); \
-} while(0)
-
#ifdef UNIV_DEBUG
/*******************************************************************//**
Assert that an autocommit non-locking select cannot be in the
@@ -1150,6 +1124,26 @@ public:
}
+ void assert_freed() const
+ {
+ ut_ad(state == TRX_STATE_NOT_STARTED);
+ ut_ad(!id);
+ ut_ad(!has_logged());
+ ut_ad(!is_referenced());
+ ut_ad(!is_wsrep());
+#ifdef WITH_WSREP
+ ut_ad(!lock.was_chosen_as_wsrep_victim);
+#endif
+ 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(UT_LIST_GET_LEN(lock.evicted_tables) == 0);
+ ut_ad(dict_operation == TRX_DICT_OP_NONE);
+ }
+
+
private:
/** Assign a rollback segment for modifying temporary tables.
@return the assigned rollback segment */
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 938df53ec49..61052b15431 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -1120,7 +1120,7 @@ wsrep_kill_victim(
}
wsrep_innobase_kill_one_trx(trx->mysql_thd,
- trx, lock->trx, TRUE);
+ lock->trx, true);
}
}
}
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index c20cf4842a0..202a5c2e009 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -209,7 +209,8 @@ dberr_t trx_rollback_for_mysql(trx_t* trx)
trx->will_lock = 0;
ut_ad(trx->mysql_thd);
#ifdef WITH_WSREP
- trx->wsrep = false;
+ trx->wsrep= false;
+ trx->lock.was_chosen_as_wsrep_victim= false;
#endif
return(DB_SUCCESS);
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index f9c8ede1f1b..47cd014a1c3 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -351,14 +351,13 @@ trx_t *trx_create()
{
trx_t* trx = trx_pools->get();
- 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->state == TRX_STATE_NOT_STARTED);
ut_ad(!trx->rw_trx_hash_pins);
DBUG_LOG("trx", "Create: " << trx);
@@ -381,7 +380,7 @@ trx_t *trx_create()
ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0);
#ifdef WITH_WSREP
- trx->wsrep_event = NULL;
+ trx->wsrep_event= NULL;
#endif /* WITH_WSREP */
trx_sys.register_trx(trx);
@@ -430,11 +429,11 @@ void trx_free(trx_t*& trx)
}
trx->dict_operation = TRX_DICT_OP_NONE;
- assert_trx_is_inactive(trx);
+ ut_ad(!trx->dict_operation_lock_mode);
trx_sys.deregister_trx(trx);
- assert_trx_is_free(trx);
+ trx->assert_freed();
trx_sys.rw_trx_hash.put_pins(trx);
trx->mysql_thd = 0;
@@ -1481,7 +1480,6 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
trx_mutex_enter(this);
dict_operation= TRX_DICT_OP_NONE;
- lock.was_chosen_as_deadlock_victim= false;
DBUG_LOG("trx", "Commit in memory: " << this);
state= TRX_STATE_NOT_STARTED;
@@ -1495,9 +1493,10 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
wsrep= false;
wsrep_commit_ordered(mysql_thd);
}
+ lock.was_chosen_as_wsrep_victim= false;
#endif /* WITH_WSREP */
- assert_trx_is_free(this);
+ assert_freed();
trx_init(this);
trx_mutex_exit(this);