diff --git a/mysql-test/suite/galera/r/galera_UK_conflict.result b/mysql-test/suite/galera/r/galera_UK_conflict.result index 44bb64c9d63..57b9c1279ea 100644 --- a/mysql-test/suite/galera/r/galera_UK_conflict.result +++ b/mysql-test/suite/galera/r/galera_UK_conflict.result @@ -119,6 +119,7 @@ SET debug_sync='RESET'; connection node_1; SET GLOBAL wsrep_slave_threads = DEFAULT; connection node_2; +SET SESSION wsrep_sync_wait=15; SELECT * FROM t1; f1 f2 f3 1 1 0 diff --git a/mysql-test/suite/galera/t/galera_UK_conflict.test b/mysql-test/suite/galera/t/galera_UK_conflict.test index 9978ba9b8bf..fa200c58ff7 100644 --- a/mysql-test/suite/galera/t/galera_UK_conflict.test +++ b/mysql-test/suite/galera/t/galera_UK_conflict.test @@ -266,6 +266,7 @@ SET debug_sync='RESET'; SET GLOBAL wsrep_slave_threads = DEFAULT; --connection node_2 +SET SESSION wsrep_sync_wait=15; SELECT * FROM t1; # replicate some transactions, so that wsrep slave thread count can reach diff --git a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result index a60e2bbb6cc..1813607517a 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result +++ b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_A.result @@ -1,6 +1,9 @@ connection node_2; connection node_1; connection node_1; +connection node_2; +connection node_3; +connection node_1; CREATE TABLE t1 (pk INT PRIMARY KEY, node INT) ENGINE=innodb; INSERT INTO t1 VALUES (1, 1); connection node_2; diff --git a/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_A.test b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_A.test index 2248ff5014a..db8bf90cb5c 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_A.test +++ b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_A.test @@ -15,6 +15,12 @@ --let $galera_server_number = 3 --source include/galera_connect.inc +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.inc + --connection node_1 --let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc @@ -260,3 +266,5 @@ call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State T --connection node_3 call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); + +--source ../galera/include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/wsrep/r/variables_debug.result b/mysql-test/suite/wsrep/r/variables_debug.result deleted file mode 100644 index 886325acf53..00000000000 --- a/mysql-test/suite/wsrep/r/variables_debug.result +++ /dev/null @@ -1,278 +0,0 @@ -call mtr.add_suppression("WSREP: Initial position was provided by configuration or SST, avoiding override"); -SET @wsrep_provider_options_saved= @@global.wsrep_provider_options; -SET @wsrep_cluster_address_saved= @@global.wsrep_cluster_address; - -# MDEV#5534: mysql_tzinfo_to_sql generates wrong query -# -# Testing wsrep_replicate_myisam variable. -SELECT @@session.wsrep_replicate_myisam; -ERROR HY000: Variable 'wsrep_replicate_myisam' is a GLOBAL variable -SELECT @@global.wsrep_replicate_myisam; -@@global.wsrep_replicate_myisam -0 -SET SESSION wsrep_replicate_myisam= ON; -ERROR HY000: Variable 'wsrep_replicate_myisam' is a GLOBAL variable and should be set with SET GLOBAL -SET GLOBAL wsrep_replicate_myisam= ON; -SET GLOBAL wsrep_replicate_myisam= OFF; -SET GLOBAL wsrep_provider=none; -# -# MDEV#5790: SHOW GLOBAL STATUS LIKE does not show the correct list of -# variables when using "_" -# -CALL mtr.add_suppression("WSREP: Could not open saved state file for reading.*"); -SHOW GLOBAL STATUS LIKE 'wsrep%'; -Variable_name Value -wsrep_local_state_uuid # -wsrep_protocol_version # -wsrep_last_committed # -wsrep_replicated # -wsrep_replicated_bytes # -wsrep_repl_keys # -wsrep_repl_keys_bytes # -wsrep_repl_data_bytes # -wsrep_repl_other_bytes # -wsrep_received # -wsrep_received_bytes # -wsrep_local_commits # -wsrep_local_cert_failures # -wsrep_local_replays # -wsrep_local_send_queue # -wsrep_local_send_queue_max # -wsrep_local_send_queue_min # -wsrep_local_send_queue_avg # -wsrep_local_recv_queue # -wsrep_local_recv_queue_max # -wsrep_local_recv_queue_min # -wsrep_local_recv_queue_avg # -wsrep_local_cached_downto # -wsrep_flow_control_paused_ns # -wsrep_flow_control_paused # -wsrep_flow_control_sent # -wsrep_flow_control_recv # -wsrep_flow_control_active # -wsrep_flow_control_requested # -wsrep_cert_deps_distance # -wsrep_apply_oooe # -wsrep_apply_oool # -wsrep_apply_window # -wsrep_commit_oooe # -wsrep_commit_oool # -wsrep_commit_window # -wsrep_local_state # -wsrep_local_state_comment # -wsrep_cert_index_size # -wsrep_causal_reads # -wsrep_cert_interval # -wsrep_open_transactions # -wsrep_open_connections # -wsrep_incoming_addresses # -wsrep_debug_sync_waiters # -wsrep_applier_thread_count # -wsrep_cluster_capabilities # -wsrep_cluster_conf_id # -wsrep_cluster_size # -wsrep_cluster_state_uuid # -wsrep_cluster_status # -wsrep_connected # -wsrep_local_bf_aborts # -wsrep_local_index # -wsrep_provider_capabilities # -wsrep_provider_name # -wsrep_provider_vendor # -wsrep_provider_version # -wsrep_ready # -wsrep_rollbacker_thread_count # -wsrep_thread_count # - -SHOW GLOBAL STATUS LIKE 'wsrep_%'; -Variable_name Value -wsrep_local_state_uuid # -wsrep_protocol_version # -wsrep_last_committed # -wsrep_replicated # -wsrep_replicated_bytes # -wsrep_repl_keys # -wsrep_repl_keys_bytes # -wsrep_repl_data_bytes # -wsrep_repl_other_bytes # -wsrep_received # -wsrep_received_bytes # -wsrep_local_commits # -wsrep_local_cert_failures # -wsrep_local_replays # -wsrep_local_send_queue # -wsrep_local_send_queue_max # -wsrep_local_send_queue_min # -wsrep_local_send_queue_avg # -wsrep_local_recv_queue # -wsrep_local_recv_queue_max # -wsrep_local_recv_queue_min # -wsrep_local_recv_queue_avg # -wsrep_local_cached_downto # -wsrep_flow_control_paused_ns # -wsrep_flow_control_paused # -wsrep_flow_control_sent # -wsrep_flow_control_recv # -wsrep_flow_control_active # -wsrep_flow_control_requested # -wsrep_cert_deps_distance # -wsrep_apply_oooe # -wsrep_apply_oool # -wsrep_apply_window # -wsrep_commit_oooe # -wsrep_commit_oool # -wsrep_commit_window # -wsrep_local_state # -wsrep_local_state_comment # -wsrep_cert_index_size # -wsrep_causal_reads # -wsrep_cert_interval # -wsrep_open_transactions # -wsrep_open_connections # -wsrep_incoming_addresses # -wsrep_debug_sync_waiters # -wsrep_applier_thread_count # -wsrep_cluster_capabilities # -wsrep_cluster_conf_id # -wsrep_cluster_size # -wsrep_cluster_state_uuid # -wsrep_cluster_status # -wsrep_connected # -wsrep_local_bf_aborts # -wsrep_local_index # -wsrep_provider_capabilities # -wsrep_provider_name # -wsrep_provider_vendor # -wsrep_provider_version # -wsrep_ready # -wsrep_rollbacker_thread_count # -wsrep_thread_count # -SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'; -Variable_name Value -wsrep_local_state_comment # -# Should show nothing. -SHOW STATUS LIKE 'x'; -Variable_name Value -SET GLOBAL wsrep_provider=none; - -SHOW STATUS LIKE 'wsrep_local_state_uuid'; -Variable_name Value -wsrep_local_state_uuid # - -SHOW STATUS LIKE 'wsrep_last_committed'; -Variable_name Value -wsrep_last_committed # -SET GLOBAL wsrep_provider=none; - -# -# MDEV#6206: wsrep_slave_threads subtracts from max_connections -# -call mtr.add_suppression("WSREP: Failed to get provider options"); -SELECT @@global.wsrep_provider; -@@global.wsrep_provider -libgalera_smm.so -SELECT @@global.wsrep_slave_threads; -@@global.wsrep_slave_threads -1 -SELECT @@global.wsrep_cluster_address; -@@global.wsrep_cluster_address - -SELECT @@global.wsrep_on; -@@global.wsrep_on -1 -SHOW STATUS LIKE 'threads_connected'; -Variable_name Value -Threads_connected 1 -SHOW STATUS LIKE 'wsrep_thread_count'; -Variable_name Value -wsrep_thread_count 0 - -SELECT @@global.wsrep_provider; -@@global.wsrep_provider -libgalera_smm.so -SELECT @@global.wsrep_cluster_address; -@@global.wsrep_cluster_address - -SELECT @@global.wsrep_on; -@@global.wsrep_on -1 -SHOW STATUS LIKE 'threads_connected'; -Variable_name Value -Threads_connected 1 -SHOW STATUS LIKE 'wsrep_thread_count'; -Variable_name Value -wsrep_thread_count 0 - -# Setting wsrep_cluster_address triggers the creation of -# applier/rollbacker threads. -SET GLOBAL wsrep_cluster_address= 'gcomm://'; -# Wait for applier thread to get created 1. -# Wait for applier thread to get created 2. -SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; -EXPECT_1 -1 -SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_rollbacker_thread_count'; -EXPECT_1 -1 -SELECT VARIABLE_VALUE AS EXPECT_2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; -EXPECT_2 -2 -SELECT @@global.wsrep_provider; -@@global.wsrep_provider -libgalera_smm.so -SELECT @@global.wsrep_cluster_address; -@@global.wsrep_cluster_address -gcomm:// -SELECT @@global.wsrep_on; -@@global.wsrep_on -1 -SHOW STATUS LIKE 'threads_connected'; -Variable_name Value -Threads_connected 1 -SHOW STATUS LIKE 'wsrep_thread_count'; -Variable_name Value -wsrep_thread_count 2 - -SET @wsrep_slave_threads_saved= @@global.wsrep_slave_threads; -SET GLOBAL wsrep_slave_threads= 10; -# Wait for 9 applier threads to get created. -SELECT VARIABLE_VALUE AS EXPECT_10 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; -EXPECT_10 -10 -SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_rollbacker_thread_count'; -EXPECT_1 -1 -SELECT VARIABLE_VALUE AS EXPECT_11 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; -EXPECT_11 -11 -SHOW STATUS LIKE 'threads_connected'; -Variable_name Value -Threads_connected 1 -set wsrep_on=0; -set wsrep_on=1; -create user test@localhost; -connect con1,localhost,test; -set auto_increment_increment=10; -set wsrep_on=0; -ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation -disconnect con1; -connection default; -drop user test@localhost; -# -# MDEV#6411: Setting set @@global.wsrep_sst_auth=NULL causes crash -# -SET @wsrep_sst_auth_saved= @@global.wsrep_sst_auth; -SET @@global.wsrep_sst_auth= 'user:pass'; -SELECT @@global.wsrep_sst_auth; -@@global.wsrep_sst_auth -******** -SET @@global.wsrep_sst_auth= ''; -SELECT @@global.wsrep_sst_auth; -@@global.wsrep_sst_auth - -SET @@global.wsrep_sst_auth= NULL; -SELECT @@global.wsrep_sst_auth; -@@global.wsrep_sst_auth -NULL -SET @@global.wsrep_sst_auth= @wsrep_sst_auth_saved; -# End of test. diff --git a/mysql-test/suite/wsrep/t/variables_debug.cnf b/mysql-test/suite/wsrep/t/variables_debug.cnf deleted file mode 100644 index b1c96d2614d..00000000000 --- a/mysql-test/suite/wsrep/t/variables_debug.cnf +++ /dev/null @@ -1,7 +0,0 @@ -!include ../my.cnf - -[mysqld.1] -wsrep-on=ON -wsrep-cluster-address=gcomm:// -wsrep-provider=@ENV.WSREP_PROVIDER -binlog-format=ROW diff --git a/mysql-test/suite/wsrep/t/variables_debug.test b/mysql-test/suite/wsrep/t/variables_debug.test deleted file mode 100644 index f2c3a0a3b78..00000000000 --- a/mysql-test/suite/wsrep/t/variables_debug.test +++ /dev/null @@ -1,176 +0,0 @@ ---source include/have_wsrep.inc ---source include/force_restart.inc ---source include/have_innodb.inc ---source include/galera_have_debug_sync.inc - -call mtr.add_suppression("WSREP: Initial position was provided by configuration or SST, avoiding override"); - -SET @wsrep_provider_options_saved= @@global.wsrep_provider_options; -SET @wsrep_cluster_address_saved= @@global.wsrep_cluster_address; - ---echo ---echo # MDEV#5534: mysql_tzinfo_to_sql generates wrong query ---echo # ---echo # Testing wsrep_replicate_myisam variable. - ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -SELECT @@session.wsrep_replicate_myisam; -SELECT @@global.wsrep_replicate_myisam; - ---error ER_GLOBAL_VARIABLE -SET SESSION wsrep_replicate_myisam= ON; -SET GLOBAL wsrep_replicate_myisam= ON; - -# Reset it back. -SET GLOBAL wsrep_replicate_myisam= OFF; -SET GLOBAL wsrep_provider=none; - ---echo # ---echo # MDEV#5790: SHOW GLOBAL STATUS LIKE does not show the correct list of ---echo # variables when using "_" ---echo # - -CALL mtr.add_suppression("WSREP: Could not open saved state file for reading.*"); - ---disable_query_log -eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; ---enable_query_log - ---replace_column 2 # -SHOW GLOBAL STATUS LIKE 'wsrep%'; - ---echo ---replace_column 2 # -SHOW GLOBAL STATUS LIKE 'wsrep_%'; - ---replace_column 2 # -SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'; - ---echo # Should show nothing. -SHOW STATUS LIKE 'x'; - -# Reset it back. -SET GLOBAL wsrep_provider=none; - ---disable_query_log -eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; ---enable_query_log - -# The following 2 variables are used by mariabackup -# SST. ---echo ---replace_column 2 # -SHOW STATUS LIKE 'wsrep_local_state_uuid'; ---echo ---replace_column 2 # -SHOW STATUS LIKE 'wsrep_last_committed'; - -# Reset it back. -SET GLOBAL wsrep_provider=none; - ---echo ---echo # ---echo # MDEV#6206: wsrep_slave_threads subtracts from max_connections ---echo # -call mtr.add_suppression("WSREP: Failed to get provider options"); - ---disable_query_log -eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; ---enable_query_log - ---replace_regex /.*libgalera_smm.*/libgalera_smm.so/ -SELECT @@global.wsrep_provider; -SELECT @@global.wsrep_slave_threads; -SELECT @@global.wsrep_cluster_address; -SELECT @@global.wsrep_on; -SHOW STATUS LIKE 'threads_connected'; -SHOW STATUS LIKE 'wsrep_thread_count'; ---echo - ---disable_query_log -eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; ---enable_query_log - ---replace_regex /.*libgalera_smm.*/libgalera_smm.so/ -SELECT @@global.wsrep_provider; -SELECT @@global.wsrep_cluster_address; -SELECT @@global.wsrep_on; -SHOW STATUS LIKE 'threads_connected'; -SHOW STATUS LIKE 'wsrep_thread_count'; ---echo - ---echo # Setting wsrep_cluster_address triggers the creation of ---echo # applier/rollbacker threads. -SET GLOBAL wsrep_cluster_address= 'gcomm://'; - ---echo # Wait for applier thread to get created 1. ---let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; ---source include/wait_condition.inc ---echo # Wait for applier thread to get created 2. ---let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_rollbacker_thread_count'; ---source include/wait_condition.inc - -SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; -SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_rollbacker_thread_count'; -SELECT VARIABLE_VALUE AS EXPECT_2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; - ---replace_regex /.*libgalera_smm.*/libgalera_smm.so/ -SELECT @@global.wsrep_provider; -SELECT @@global.wsrep_cluster_address; -SELECT @@global.wsrep_on; -SHOW STATUS LIKE 'threads_connected'; -SHOW STATUS LIKE 'wsrep_thread_count'; ---echo - -SET @wsrep_slave_threads_saved= @@global.wsrep_slave_threads; -SET GLOBAL wsrep_slave_threads= 10; - ---echo # Wait for 9 applier threads to get created. ---let $wait_condition = SELECT VARIABLE_VALUE = 10 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; ---source include/wait_condition.inc - -SELECT VARIABLE_VALUE AS EXPECT_10 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; -SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_rollbacker_thread_count'; -SELECT VARIABLE_VALUE AS EXPECT_11 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; - -SHOW STATUS LIKE 'threads_connected'; - -# -# privileges for wsrep_on -# -set wsrep_on=0; -set wsrep_on=1; ---source include/wait_until_connected_again.inc -create user test@localhost; -connect con1,localhost,test; -set auto_increment_increment=10; ---error ER_SPECIFIC_ACCESS_DENIED_ERROR -set wsrep_on=0; -disconnect con1; -connection default; -drop user test@localhost; - ---echo # ---echo # MDEV#6411: Setting set @@global.wsrep_sst_auth=NULL causes crash ---echo # -SET @wsrep_sst_auth_saved= @@global.wsrep_sst_auth; -SET @@global.wsrep_sst_auth= 'user:pass'; -SELECT @@global.wsrep_sst_auth; -SET @@global.wsrep_sst_auth= ''; -SELECT @@global.wsrep_sst_auth; -SET @@global.wsrep_sst_auth= NULL; -SELECT @@global.wsrep_sst_auth; -SET @@global.wsrep_sst_auth= @wsrep_sst_auth_saved; - -# Reset (for mtr internal checks) - ---disable_query_log -SET GLOBAL wsrep_slave_threads= @wsrep_slave_threads_saved; -eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; -SET GLOBAL wsrep_cluster_address= @wsrep_cluster_address_saved; -SET GLOBAL wsrep_provider_options= @wsrep_provider_options_saved; ---enable_query_log - ---source include/galera_wait_ready.inc - ---echo # End of test. diff --git a/sql/log.cc b/sql/log.cc index 894fecf93f1..a31b8dd5598 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -7972,7 +7972,6 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry) DBUG_ASSERT(entry != NULL); cur= entry->thd->wait_for_commit_ptr; } - #ifdef WITH_WSREP if (wsrep_is_active(entry->thd) && wsrep_run_commit_hook(entry->thd, entry->all)) @@ -7986,7 +7985,7 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry) result= -3; } else - DBUG_ASSERT(result != -2 && result != -3); + DBUG_ASSERT(result == 0); #endif /* WITH_WSREP */ if (opt_binlog_commit_wait_count > 0 && orig_queue != NULL) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cca08c9007f..ad5034f5228 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1206,7 +1206,8 @@ dispatch_command_return do_command(THD *thd, bool blocking) enum enum_server_command command; DBUG_ENTER("do_command"); - DBUG_ASSERT(!thd->async_state.pending_ops()); + DBUG_ASSERT(!thd->async_state.pending_ops() || + (WSREP(thd) && thd->wsrep_trx().state() == wsrep::transaction::s_aborted)); if (thd->async_state.m_state == thd_async_state::enum_async_state::RESUMED) { /* diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 15fd87eda5d..e4e598d472a 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -348,8 +348,23 @@ bool wsrep_bf_abort(const THD* bf_thd, THD* victim_thd) if (WSREP(victim_thd) && !victim_thd->wsrep_trx().active()) { - WSREP_DEBUG("wsrep_bf_abort, BF abort for non active transaction"); - wsrep_start_transaction(victim_thd, victim_thd->wsrep_next_trx_id()); + WSREP_DEBUG("wsrep_bf_abort, BF abort for non active transaction." + " Victim state %s bf state %s", + wsrep::to_c_string(victim_thd->wsrep_trx().state()), + wsrep::to_c_string(bf_thd->wsrep_trx().state())); + + switch (victim_thd->wsrep_trx().state()) { + case wsrep::transaction::s_aborting: /* fall through */ + case wsrep::transaction::s_aborted: + WSREP_DEBUG("victim is aborting or has aborted"); + break; + default: break; + } + /* victim may not have started transaction yet in wsrep context, but it may + have acquired MDL locks (due to DDL execution), and this has caused BF conflict. + such case does not require aborting in wsrep or replication provider state. + */ + return false; } bool ret; @@ -359,6 +374,7 @@ bool wsrep_bf_abort(const THD* bf_thd, THD* victim_thd) } else { + DBUG_ASSERT(WSREP(victim_thd) ? victim_thd->wsrep_trx().active() : 1); ret= victim_thd->wsrep_cs().bf_abort(bf_seqno); } if (ret) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 4440fe62fa5..7ffbe3fe374 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18075,41 +18075,53 @@ void lock_wait_wsrep_kill(trx_t *bf_trx, ulong thd_id, trx_id_t trx_id) { bool aborting= false; wsrep_thd_LOCK(vthd); - if (trx_t *vtrx= thd_to_trx(vthd)) + trx_t *vtrx= thd_to_trx(vthd); + if (vtrx) { lock_sys.wr_lock(SRW_LOCK_CALL); mysql_mutex_lock(&lock_sys.wait_mutex); vtrx->mutex_lock(); - if (vtrx->id == trx_id && vtrx->state == TRX_STATE_ACTIVE) + /* victim transaction is either active or prepared, if it has already + proceeded to replication phase */ + if (vtrx->id == trx_id) { - WSREP_LOG_CONFLICT(bf_thd, vthd, TRUE); - WSREP_DEBUG("Aborter BF trx_id: " TRX_ID_FMT " thread: %ld " - "seqno: %lld client_state: %s " - "client_mode: %s transaction_mode: %s query: %s", - bf_trx->id, - 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(vthd, false) ? "BF" : "normal", - vtrx->id, - thd_get_thread_id(vthd), - wsrep_thd_trx_seqno(vthd), - wsrep_thd_client_state_str(vthd), - wsrep_thd_client_mode_str(vthd), - wsrep_thd_transaction_state_str(vthd), - wsrep_thd_query(vthd)); - /* Mark transaction as a victim for Galera abort */ - vtrx->lock.was_chosen_as_deadlock_victim.fetch_or(2); - if (!wsrep_thd_set_wsrep_aborter(bf_thd, vthd)) - aborting= true; - else - WSREP_DEBUG("kill transaction skipped due to wsrep_aborter set"); + switch (vtrx->state) { + default: + break; + case TRX_STATE_PREPARED: + if (!wsrep_is_wsrep_xid(vtrx->xid)) + break; + /* fall through */ + case TRX_STATE_ACTIVE: + WSREP_LOG_CONFLICT(bf_thd, vthd, TRUE); + WSREP_DEBUG("Aborter BF trx_id: " TRX_ID_FMT " thread: %ld " + "seqno: %lld client_state: %s " + "client_mode: %s transaction_mode: %s query: %s", + bf_trx->id, + 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(vthd, false) ? "BF" : "normal", + vtrx->id, + thd_get_thread_id(vthd), + wsrep_thd_trx_seqno(vthd), + wsrep_thd_client_state_str(vthd), + wsrep_thd_client_mode_str(vthd), + wsrep_thd_transaction_state_str(vthd), + wsrep_thd_query(vthd)); + /* Mark transaction as a victim for Galera abort */ + vtrx->lock.was_chosen_as_deadlock_victim.fetch_or(2); + if (!wsrep_thd_set_wsrep_aborter(bf_thd, vthd)) + aborting= true; + else + WSREP_DEBUG("kill transaction skipped due to wsrep_aborter set"); + } } lock_sys.wr_unlock(); mysql_mutex_unlock(&lock_sys.wait_mutex); @@ -18118,6 +18130,11 @@ void lock_wait_wsrep_kill(trx_t *bf_trx, ulong thd_id, trx_id_t trx_id) wsrep_thd_UNLOCK(vthd); if (aborting) { + /* if victim is waiting for some other lock, we have to cancel + that waiting + */ + lock_sys.cancel_lock_wait_for_trx(vtrx); + DEBUG_SYNC(bf_thd, "before_wsrep_thd_abort"); wsrep_thd_bf_abort(bf_thd, vthd, true); } @@ -18146,7 +18163,7 @@ wsrep_abort_transaction( ut_ad(bf_thd); ut_ad(victim_thd); - trx_t* victim_trx = thd_to_trx(victim_thd); + trx_t* victim_trx= thd_to_trx(victim_thd); WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %s", wsrep_thd_query(bf_thd), diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 8e38b99c121..b96f54e03a3 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -859,6 +859,11 @@ public: @param id page to be discarded @param page whether to discard also from lock_sys.prdt_hash */ void prdt_page_free_from_discard(const page_id_t id, bool all= false); + +#ifdef WITH_WSREP + /** Cancel possible lock waiting for a transaction */ + static void cancel_lock_wait_for_trx(trx_t *trx); +#endif /* WITH_WSREP */ }; /** The lock system */ diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 756902690c2..62582e61b0b 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -921,8 +921,13 @@ func_exit: dict_table_t *table= wait_lock->un_member.tab_lock.table; for (lock_t *lock= UT_LIST_GET_FIRST(table->locks); lock; lock= UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) - if (lock->trx != trx) + /* if victim has also BF status, but has earlier seqno, we have to wait */ + if (lock->trx != trx && + !(wsrep_thd_is_BF(lock->trx->mysql_thd, false) && + wsrep_thd_order_before(lock->trx->mysql_thd, trx->mysql_thd))) + { victims.emplace(lock->trx); + } } else { @@ -936,8 +941,13 @@ func_exit: if (!lock_rec_get_nth_bit(lock, heap_no)) lock= lock_rec_get_next(heap_no, lock); do - if (lock->trx != trx) + /* if victim has also BF status, but has earlier seqno, we have to wait */ + if (lock->trx != trx && + !(wsrep_thd_is_BF(lock->trx->mysql_thd, false) && + wsrep_thd_order_before(lock->trx->mysql_thd, trx->mysql_thd))) + { victims.emplace(lock->trx); + } while ((lock= lock_rec_get_next(heap_no, lock))); } } @@ -5362,6 +5372,21 @@ static void lock_cancel_waiting_and_release(lock_t *lock) lock_wait_end(trx); trx->mutex_unlock(); } +#ifdef WITH_WSREP +void lock_sys_t::cancel_lock_wait_for_trx(trx_t *trx) +{ + lock_sys.wr_lock(SRW_LOCK_CALL); + mysql_mutex_lock(&lock_sys.wait_mutex); + if (lock_t *lock= trx->lock.wait_lock) + { + /* check if victim is still waiting */ + if (lock->is_waiting()) + lock_cancel_waiting_and_release(lock); + } + lock_sys.wr_unlock(); + mysql_mutex_unlock(&lock_sys.wait_mutex); +} +#endif /* WITH_WSREP */ /** Cancel a waiting lock request. @param lock waiting lock request @@ -5758,8 +5783,15 @@ namespace Deadlock If current_trx=false, a concurrent commit is protected by both lock_sys.latch and lock_sys.wait_mutex. */ const undo_no_t trx_weight= TRX_WEIGHT(trx) | - (trx->mysql_thd && thd_has_edited_nontrans_tables(trx->mysql_thd) + (trx->mysql_thd && +#ifdef WITH_WSREP + (thd_has_edited_nontrans_tables(trx->mysql_thd) || + (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, false))) +#else + thd_has_edited_nontrans_tables(trx->mysql_thd) +#endif /* WITH_WSREP */ ? 1ULL << 63 : 0); + trx_t *victim= nullptr; undo_no_t victim_weight= ~0ULL; unsigned victim_pos= 0, trx_pos= 0; @@ -5782,7 +5814,13 @@ namespace Deadlock { next= next->lock.wait_trx; const undo_no_t next_weight= TRX_WEIGHT(next) | - (next->mysql_thd && thd_has_edited_nontrans_tables(next->mysql_thd) + (next->mysql_thd && +#ifdef WITH_WSREP + (thd_has_edited_nontrans_tables(next->mysql_thd) || + (next->is_wsrep() && wsrep_thd_is_BF(next->mysql_thd, false))) +#else + thd_has_edited_nontrans_tables(next->mysql_thd) +#endif /* WITH_WSREP */ ? 1ULL << 63 : 0); if (next_weight < victim_weight) {