2022-10-12 13:13:49 +02:00
|
|
|
/* Copyright 2018-2023 Codership Oy <info@codership.com>
|
2019-01-23 12:30:00 +01:00
|
|
|
|
|
|
|
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 Foundation; version 2 of the License.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#include "mariadb.h"
|
|
|
|
|
|
|
|
#include "mysql/service_wsrep.h"
|
|
|
|
#include "wsrep/key.hpp"
|
|
|
|
#include "wsrep_thd.h"
|
|
|
|
#include "wsrep_trans_observer.h"
|
|
|
|
#include "sql_class.h"
|
|
|
|
#include "debug_sync.h"
|
2019-03-15 06:09:13 +01:00
|
|
|
#include "log.h"
|
2019-01-23 12:30:00 +01:00
|
|
|
|
|
|
|
extern "C" my_bool wsrep_on(const THD *thd)
|
|
|
|
{
|
|
|
|
return my_bool(WSREP(thd));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void wsrep_thd_LOCK(const THD *thd)
|
|
|
|
{
|
2021-10-21 13:49:51 +02:00
|
|
|
mysql_mutex_lock(&thd->LOCK_thd_kill);
|
2019-01-23 12:30:00 +01:00
|
|
|
mysql_mutex_lock(&thd->LOCK_thd_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void wsrep_thd_UNLOCK(const THD *thd)
|
|
|
|
{
|
|
|
|
mysql_mutex_unlock(&thd->LOCK_thd_data);
|
2021-10-21 13:49:51 +02:00
|
|
|
mysql_mutex_unlock(&thd->LOCK_thd_kill);
|
2019-01-23 12:30:00 +01:00
|
|
|
}
|
|
|
|
|
2021-02-12 17:44:22 +01:00
|
|
|
extern "C" void wsrep_thd_kill_LOCK(const THD *thd)
|
|
|
|
{
|
|
|
|
mysql_mutex_lock(&thd->LOCK_thd_kill);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void wsrep_thd_kill_UNLOCK(const THD *thd)
|
|
|
|
{
|
|
|
|
mysql_mutex_unlock(&thd->LOCK_thd_kill);
|
|
|
|
}
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
extern "C" const char* wsrep_thd_client_state_str(const THD *thd)
|
|
|
|
{
|
|
|
|
return wsrep::to_c_string(thd->wsrep_cs().state());
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" const char* wsrep_thd_client_mode_str(const THD *thd)
|
|
|
|
{
|
|
|
|
return wsrep::to_c_string(thd->wsrep_cs().mode());
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" const char* wsrep_thd_transaction_state_str(const THD *thd)
|
|
|
|
{
|
|
|
|
return wsrep::to_c_string(thd->wsrep_cs().transaction().state());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" const char *wsrep_thd_query(const THD *thd)
|
|
|
|
{
|
2019-11-01 14:23:18 +01:00
|
|
|
if (thd)
|
|
|
|
{
|
|
|
|
switch(thd->lex->sql_command)
|
|
|
|
{
|
|
|
|
case SQLCOM_CREATE_USER:
|
|
|
|
return "CREATE USER";
|
|
|
|
case SQLCOM_GRANT:
|
|
|
|
return "GRANT";
|
|
|
|
case SQLCOM_REVOKE:
|
|
|
|
return "REVOKE";
|
|
|
|
case SQLCOM_SET_OPTION:
|
|
|
|
if (thd->lex->definer)
|
|
|
|
return "SET PASSWORD";
|
|
|
|
/* fallthrough */
|
|
|
|
default:
|
|
|
|
if (thd->query())
|
|
|
|
return thd->query();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "NULL";
|
2019-01-23 12:30:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" query_id_t wsrep_thd_transaction_id(const THD *thd)
|
|
|
|
{
|
|
|
|
return thd->wsrep_cs().transaction().id().get();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" long long wsrep_thd_trx_seqno(const THD *thd)
|
|
|
|
{
|
|
|
|
const wsrep::client_state& cs= thd->wsrep_cs();
|
|
|
|
if (cs.mode() == wsrep::client_state::m_toi)
|
|
|
|
{
|
|
|
|
return cs.toi_meta().seqno().get();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return cs.transaction().ws_meta().seqno().get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void wsrep_thd_self_abort(THD *thd)
|
|
|
|
{
|
|
|
|
thd->wsrep_cs().bf_abort(wsrep::seqno(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" const char* wsrep_get_sr_table_name()
|
|
|
|
{
|
|
|
|
return wsrep_sr_table_name_full;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_get_debug()
|
|
|
|
{
|
|
|
|
return wsrep_debug;
|
|
|
|
}
|
|
|
|
|
2021-04-14 22:40:46 +02:00
|
|
|
/*
|
|
|
|
Test if this connection is a true local (user) connection and not
|
|
|
|
a replication or wsrep applier thread.
|
|
|
|
|
|
|
|
Note that this is only usable for galera (as there are other kinds
|
|
|
|
of system threads, and only if WSREP_NNULL() is tested by the caller.
|
|
|
|
*/
|
2019-01-23 12:30:00 +01:00
|
|
|
extern "C" my_bool wsrep_thd_is_local(const THD *thd)
|
|
|
|
{
|
MDEV-21096 async slave crash with gtid_log_pos table access (#1413)
The original crash happened when async replication IO thread was updating mysql.gtid_slave_pos table. Operations on this table should remain node local, but it appears that protection (THD::wsrep_ignore_table flag) to prevent wsrep replication for this table mas missing for innodb write_row() and update_row().
It was somewhat difficult to reproduce the issue, because mtr seems to create the affected table mysql.gtid_log_pos as of Aria engine type, and Aria engine operations will not be replicated anyhow. It looks, though, that in release installation, mysql.gtid_slave_pos table is of InnoDB engine.
It was possible to trigger somewhat related problem by running test galera.galera_as_slave_gtid with configuration: gtid_pos_auto_engines=InnoDB. However, this test mode, causes earlier crash when replication background thread creates aditional table: mysql.gtid_slave_pos_InnoDB, and this table create triggered wsrep TOI replication, which also failed for assertion. Actually, async replication IO and background threads should not replicate anything to cluster.
This pull request contains new test galera.galera_as_slave_gtid_auto_engine, which basically just runs galera.galera_as_slave_gtid with configuration of gtid_pos_auto_engines=InnoDB.
Test galera.galera_as_slave_gtid is also modified for better code reuse.
Actual fix for MDEV-21096 is in storage/innobase/handler/ha_innodb.cc, where THD::wsrep_ignore_table flag is now honored before wsrep key population.
There is additional fix in sql/service_wsrep.cc where async replication IO and background threads are marked as non-local. This fences these threads out of wsrep replication altogether. Note that this change, actually makes the use of THD::wsrep_ignore-table redundant. We may want to refactor THD::wsrep_ignore_table out in the future, if there is no other use case for it in sight.
2019-11-25 10:19:33 +01:00
|
|
|
/*
|
2021-04-14 22:40:46 +02:00
|
|
|
async replication IO and background threads have nothing to
|
|
|
|
replicate in the cluster, marking them as non-local here to
|
|
|
|
prevent write set population and replication
|
MDEV-21096 async slave crash with gtid_log_pos table access (#1413)
The original crash happened when async replication IO thread was updating mysql.gtid_slave_pos table. Operations on this table should remain node local, but it appears that protection (THD::wsrep_ignore_table flag) to prevent wsrep replication for this table mas missing for innodb write_row() and update_row().
It was somewhat difficult to reproduce the issue, because mtr seems to create the affected table mysql.gtid_log_pos as of Aria engine type, and Aria engine operations will not be replicated anyhow. It looks, though, that in release installation, mysql.gtid_slave_pos table is of InnoDB engine.
It was possible to trigger somewhat related problem by running test galera.galera_as_slave_gtid with configuration: gtid_pos_auto_engines=InnoDB. However, this test mode, causes earlier crash when replication background thread creates aditional table: mysql.gtid_slave_pos_InnoDB, and this table create triggered wsrep TOI replication, which also failed for assertion. Actually, async replication IO and background threads should not replicate anything to cluster.
This pull request contains new test galera.galera_as_slave_gtid_auto_engine, which basically just runs galera.galera_as_slave_gtid with configuration of gtid_pos_auto_engines=InnoDB.
Test galera.galera_as_slave_gtid is also modified for better code reuse.
Actual fix for MDEV-21096 is in storage/innobase/handler/ha_innodb.cc, where THD::wsrep_ignore_table flag is now honored before wsrep key population.
There is additional fix in sql/service_wsrep.cc where async replication IO and background threads are marked as non-local. This fences these threads out of wsrep replication altogether. Note that this change, actually makes the use of THD::wsrep_ignore-table redundant. We may want to refactor THD::wsrep_ignore_table out in the future, if there is no other use case for it in sight.
2019-11-25 10:19:33 +01:00
|
|
|
|
2021-04-14 22:40:46 +02:00
|
|
|
async replication SQL thread, applies client transactions from
|
|
|
|
mariadb master and will be replicated into cluster
|
|
|
|
*/
|
MDEV-21096 async slave crash with gtid_log_pos table access (#1413)
The original crash happened when async replication IO thread was updating mysql.gtid_slave_pos table. Operations on this table should remain node local, but it appears that protection (THD::wsrep_ignore_table flag) to prevent wsrep replication for this table mas missing for innodb write_row() and update_row().
It was somewhat difficult to reproduce the issue, because mtr seems to create the affected table mysql.gtid_log_pos as of Aria engine type, and Aria engine operations will not be replicated anyhow. It looks, though, that in release installation, mysql.gtid_slave_pos table is of InnoDB engine.
It was possible to trigger somewhat related problem by running test galera.galera_as_slave_gtid with configuration: gtid_pos_auto_engines=InnoDB. However, this test mode, causes earlier crash when replication background thread creates aditional table: mysql.gtid_slave_pos_InnoDB, and this table create triggered wsrep TOI replication, which also failed for assertion. Actually, async replication IO and background threads should not replicate anything to cluster.
This pull request contains new test galera.galera_as_slave_gtid_auto_engine, which basically just runs galera.galera_as_slave_gtid with configuration of gtid_pos_auto_engines=InnoDB.
Test galera.galera_as_slave_gtid is also modified for better code reuse.
Actual fix for MDEV-21096 is in storage/innobase/handler/ha_innodb.cc, where THD::wsrep_ignore_table flag is now honored before wsrep key population.
There is additional fix in sql/service_wsrep.cc where async replication IO and background threads are marked as non-local. This fences these threads out of wsrep replication altogether. Note that this change, actually makes the use of THD::wsrep_ignore-table redundant. We may want to refactor THD::wsrep_ignore_table out in the future, if there is no other use case for it in sight.
2019-11-25 10:19:33 +01:00
|
|
|
return (
|
|
|
|
thd->system_thread != SYSTEM_THREAD_SLAVE_BACKGROUND &&
|
|
|
|
thd->system_thread != SYSTEM_THREAD_SLAVE_IO &&
|
|
|
|
thd->wsrep_cs().mode() == wsrep::client_state::m_local);
|
2019-01-23 12:30:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_is_applying(const THD *thd)
|
|
|
|
{
|
|
|
|
return thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_is_toi(const THD *thd)
|
|
|
|
{
|
|
|
|
return thd->wsrep_cs().mode() == wsrep::client_state::m_toi;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_is_local_toi(const THD *thd)
|
|
|
|
{
|
|
|
|
return thd->wsrep_cs().mode() == wsrep::client_state::m_toi &&
|
|
|
|
thd->wsrep_cs().toi_mode() == wsrep::client_state::m_local;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_is_in_rsu(const THD *thd)
|
|
|
|
{
|
|
|
|
return thd->wsrep_cs().mode() == wsrep::client_state::m_rsu;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_is_BF(const THD *thd, my_bool sync)
|
|
|
|
{
|
|
|
|
my_bool status = FALSE;
|
|
|
|
if (thd && WSREP(thd))
|
|
|
|
{
|
|
|
|
if (sync) mysql_mutex_lock(&thd->LOCK_thd_data);
|
|
|
|
status = (wsrep_thd_is_applying(thd) || wsrep_thd_is_toi(thd));
|
|
|
|
if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data);
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_is_SR(const THD *thd)
|
|
|
|
{
|
|
|
|
return thd && thd->wsrep_cs().transaction().is_streaming();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void wsrep_handle_SR_rollback(THD *bf_thd,
|
|
|
|
THD *victim_thd)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(victim_thd);
|
2020-02-24 17:04:43 +01:00
|
|
|
DBUG_ASSERT(wsrep_thd_is_SR(victim_thd));
|
2019-01-23 12:30:00 +01:00
|
|
|
if (!victim_thd || !wsrep_on(bf_thd)) return;
|
|
|
|
|
2021-10-21 13:49:51 +02:00
|
|
|
wsrep_thd_LOCK(victim_thd);
|
|
|
|
|
2019-04-03 08:19:12 +02:00
|
|
|
WSREP_DEBUG("handle rollback, for deadlock: thd %llu trx_id %" PRIu64 " frags %zu conf %s",
|
2019-01-23 12:30:00 +01:00
|
|
|
victim_thd->thread_id,
|
|
|
|
victim_thd->wsrep_trx_id(),
|
|
|
|
victim_thd->wsrep_sr().fragments_certified(),
|
|
|
|
wsrep_thd_transaction_state_str(victim_thd));
|
2019-08-30 07:42:24 +02:00
|
|
|
|
|
|
|
/* Note: do not store/reset globals before wsrep_bf_abort() call
|
|
|
|
to avoid losing BF thd context. */
|
|
|
|
if (!(bf_thd && bf_thd != victim_thd))
|
2019-01-23 12:30:00 +01:00
|
|
|
{
|
|
|
|
DEBUG_SYNC(victim_thd, "wsrep_before_SR_rollback");
|
|
|
|
}
|
|
|
|
if (bf_thd)
|
|
|
|
{
|
|
|
|
wsrep_bf_abort(bf_thd, victim_thd);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wsrep_thd_self_abort(victim_thd);
|
|
|
|
}
|
2021-10-21 13:49:51 +02:00
|
|
|
|
|
|
|
wsrep_thd_UNLOCK(victim_thd);
|
|
|
|
|
2019-08-30 07:42:24 +02:00
|
|
|
if (bf_thd)
|
2019-02-19 13:08:29 +01:00
|
|
|
{
|
2019-08-30 07:42:24 +02:00
|
|
|
wsrep_store_threadvars(bf_thd);
|
2019-02-19 13:08:29 +01:00
|
|
|
}
|
2019-01-23 12:30:00 +01:00
|
|
|
}
|
|
|
|
|
2019-12-04 08:21:14 +01:00
|
|
|
extern "C" my_bool wsrep_thd_bf_abort(THD *bf_thd, THD *victim_thd,
|
2019-01-23 12:30:00 +01:00
|
|
|
my_bool signal)
|
|
|
|
{
|
2021-10-21 13:49:51 +02:00
|
|
|
mysql_mutex_assert_owner(&victim_thd->LOCK_thd_kill);
|
|
|
|
mysql_mutex_assert_owner(&victim_thd->LOCK_thd_data);
|
2022-09-23 16:37:52 +02:00
|
|
|
#ifdef ENABLED_DEBUG_SYNC
|
2021-10-22 08:50:11 +02:00
|
|
|
DBUG_EXECUTE_IF("sync.before_wsrep_thd_abort",
|
|
|
|
{
|
|
|
|
const char act[]=
|
|
|
|
"now "
|
|
|
|
"SIGNAL sync.before_wsrep_thd_abort_reached "
|
|
|
|
"WAIT_FOR signal.before_wsrep_thd_abort";
|
|
|
|
DBUG_ASSERT(!debug_sync_set_action(bf_thd,
|
|
|
|
STRING_WITH_LEN(act)));
|
|
|
|
};);
|
2022-09-23 16:37:52 +02:00
|
|
|
#endif
|
2019-01-23 12:30:00 +01:00
|
|
|
my_bool ret= wsrep_bf_abort(bf_thd, victim_thd);
|
|
|
|
/*
|
|
|
|
Send awake signal if victim was BF aborted or does not
|
|
|
|
have wsrep on. Note that this should never interrupt RSU
|
|
|
|
as RSU has paused the provider.
|
|
|
|
*/
|
2021-10-21 13:49:51 +02:00
|
|
|
mysql_mutex_assert_owner(&victim_thd->LOCK_thd_data);
|
|
|
|
mysql_mutex_assert_owner(&victim_thd->LOCK_thd_kill);
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
if ((ret || !wsrep_on(victim_thd)) && signal)
|
2020-05-14 08:17:14 +02:00
|
|
|
{
|
2020-05-19 10:12:26 +02:00
|
|
|
if (victim_thd->wsrep_aborter && victim_thd->wsrep_aborter != bf_thd->thread_id)
|
|
|
|
{
|
|
|
|
WSREP_DEBUG("victim is killed already by %llu, skipping awake",
|
|
|
|
victim_thd->wsrep_aborter);
|
2021-10-21 13:49:51 +02:00
|
|
|
wsrep_thd_UNLOCK(victim_thd);
|
2020-05-19 10:12:26 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
victim_thd->wsrep_aborter= bf_thd->thread_id;
|
2020-05-14 08:17:14 +02:00
|
|
|
victim_thd->awake_no_mutex(KILL_QUERY);
|
|
|
|
}
|
2021-10-21 13:49:51 +02:00
|
|
|
else
|
|
|
|
WSREP_DEBUG("wsrep_thd_bf_abort skipped awake for %llu", thd_get_thread_id(victim_thd));
|
|
|
|
|
|
|
|
wsrep_thd_UNLOCK(victim_thd);
|
2019-01-23 12:30:00 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_skip_locking(const THD *thd)
|
|
|
|
{
|
|
|
|
return thd && thd->wsrep_skip_locking;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_order_before(const THD *left, const THD *right)
|
|
|
|
{
|
2022-10-12 13:13:49 +02:00
|
|
|
if (wsrep_thd_is_BF(left, false) &&
|
|
|
|
wsrep_thd_is_BF(right, false) &&
|
|
|
|
wsrep_thd_trx_seqno(left) < wsrep_thd_trx_seqno(right)) {
|
2019-01-23 12:30:00 +01:00
|
|
|
WSREP_DEBUG("BF conflict, order: %lld %lld\n",
|
|
|
|
(long long)wsrep_thd_trx_seqno(left),
|
|
|
|
(long long)wsrep_thd_trx_seqno(right));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n",
|
|
|
|
(long long)wsrep_thd_trx_seqno(left),
|
|
|
|
(long long)wsrep_thd_trx_seqno(right));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" my_bool wsrep_thd_is_aborting(const MYSQL_THD thd)
|
|
|
|
{
|
2021-09-17 14:20:02 +02:00
|
|
|
const wsrep::client_state& cs(thd->wsrep_cs());
|
|
|
|
const enum wsrep::transaction::state tx_state(cs.transaction().state());
|
|
|
|
switch (tx_state)
|
2019-01-23 12:30:00 +01:00
|
|
|
{
|
|
|
|
case wsrep::transaction::s_must_abort:
|
|
|
|
return (cs.state() == wsrep::client_state::s_exec ||
|
|
|
|
cs.state() == wsrep::client_state::s_result);
|
|
|
|
case wsrep::transaction::s_aborting:
|
|
|
|
case wsrep::transaction::s_aborted:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline enum wsrep::key::type
|
|
|
|
map_key_type(enum Wsrep_service_key_type type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case WSREP_SERVICE_KEY_SHARED: return wsrep::key::shared;
|
|
|
|
case WSREP_SERVICE_KEY_REFERENCE: return wsrep::key::reference;
|
|
|
|
case WSREP_SERVICE_KEY_UPDATE: return wsrep::key::update;
|
|
|
|
case WSREP_SERVICE_KEY_EXCLUSIVE: return wsrep::key::exclusive;
|
|
|
|
}
|
|
|
|
return wsrep::key::exclusive;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int wsrep_thd_append_key(THD *thd,
|
|
|
|
const struct wsrep_key* key,
|
|
|
|
int n_keys,
|
|
|
|
enum Wsrep_service_key_type key_type)
|
|
|
|
{
|
|
|
|
Wsrep_client_state& client_state(thd->wsrep_cs());
|
|
|
|
DBUG_ASSERT(client_state.transaction().active());
|
|
|
|
int ret= 0;
|
|
|
|
for (int i= 0; i < n_keys && ret == 0; ++i)
|
|
|
|
{
|
|
|
|
wsrep::key wsrep_key(map_key_type(key_type));
|
|
|
|
for (size_t kp= 0; kp < key[i].key_parts_num; ++kp)
|
|
|
|
{
|
|
|
|
wsrep_key.append_key_part(key[i].key_parts[kp].ptr, key[i].key_parts[kp].len);
|
|
|
|
}
|
|
|
|
ret= client_state.append_key(wsrep_key);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2019-03-15 06:09:13 +01:00
|
|
|
|
|
|
|
extern "C" void wsrep_commit_ordered(THD *thd)
|
|
|
|
{
|
|
|
|
if (wsrep_is_active(thd) &&
|
|
|
|
thd->wsrep_trx().state() == wsrep::transaction::s_committing &&
|
|
|
|
!wsrep_commit_will_write_binlog(thd))
|
|
|
|
{
|
2020-05-25 13:23:42 +02:00
|
|
|
DEBUG_SYNC(thd, "before_wsrep_ordered_commit");
|
2019-03-15 06:09:13 +01:00
|
|
|
thd->wsrep_cs().ordered_commit();
|
|
|
|
}
|
|
|
|
}
|
2020-05-19 10:12:26 +02:00
|
|
|
|
|
|
|
extern "C" bool wsrep_thd_set_wsrep_aborter(THD *bf_thd, THD *victim_thd)
|
|
|
|
{
|
|
|
|
mysql_mutex_assert_owner(&victim_thd->LOCK_thd_data);
|
2022-10-06 14:16:06 +02:00
|
|
|
if (!bf_thd)
|
|
|
|
{
|
|
|
|
victim_thd->wsrep_aborter= 0;
|
|
|
|
WSREP_DEBUG("wsrep_thd_set_wsrep_aborter resetting wsrep_aborter");
|
|
|
|
return false;
|
|
|
|
}
|
2020-05-19 10:12:26 +02:00
|
|
|
if (victim_thd->wsrep_aborter && victim_thd->wsrep_aborter != bf_thd->thread_id)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2022-10-06 14:16:06 +02:00
|
|
|
victim_thd->wsrep_aborter= bf_thd->thread_id;
|
|
|
|
WSREP_DEBUG("wsrep_thd_set_wsrep_aborter setting wsrep_aborter %u",
|
|
|
|
victim_thd->wsrep_aborter);
|
2020-05-19 10:12:26 +02:00
|
|
|
return false;
|
|
|
|
}
|
2020-09-21 11:29:00 +02:00
|
|
|
|
|
|
|
extern "C" void wsrep_report_bf_lock_wait(const THD *thd,
|
|
|
|
unsigned long long trx_id)
|
|
|
|
{
|
|
|
|
if (thd)
|
|
|
|
{
|
|
|
|
WSREP_ERROR("Thread %s trx_id: %llu thread: %ld "
|
|
|
|
"seqno: %lld client_state: %s client_mode: %s transaction_mode: %s "
|
|
|
|
"applier: %d toi: %d local: %d "
|
|
|
|
"query: %s",
|
|
|
|
wsrep_thd_is_BF(thd, false) ? "BF" : "normal",
|
|
|
|
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_is_applying(thd),
|
|
|
|
wsrep_thd_is_toi(thd),
|
|
|
|
wsrep_thd_is_local(thd),
|
|
|
|
wsrep_thd_query(thd));
|
|
|
|
}
|
|
|
|
}
|
2021-12-09 17:12:20 +01:00
|
|
|
|
|
|
|
extern "C" void wsrep_thd_set_PA_unsafe(THD *thd)
|
|
|
|
{
|
|
|
|
if (thd && thd->wsrep_cs().mark_transaction_pa_unsafe())
|
|
|
|
{
|
|
|
|
WSREP_DEBUG("session does not have active transaction, can not mark as PA unsafe");
|
|
|
|
}
|
|
|
|
}
|