Skip to content

Commit

Permalink
perfschema transaction instrumentation related changes
Browse files Browse the repository at this point in the history
  • Loading branch information
vuvova committed Mar 10, 2020
1 parent 6ded554 commit 81cffda
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 41 deletions.
90 changes: 86 additions & 4 deletions sql/handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "myisam.h"
#include "probes_mysql.h"
#include <mysql/psi/mysql_table.h>
#include <pfs_transaction_provider.h>
#include <mysql/psi/mysql_transaction.h>
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_audit.h"
#include "ha_sequence.h"
Expand All @@ -62,6 +64,39 @@
#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
#endif /* WITH_WSREP */

/**
@def MYSQL_TABLE_LOCK_WAIT
Instrumentation helper for table io_waits.
@param OP the table operation to be performed
@param FLAGS per table operation flags.
@param PAYLOAD the code to instrument.
@sa MYSQL_END_TABLE_WAIT.
*/
#ifdef HAVE_PSI_TABLE_INTERFACE
#define MYSQL_TABLE_LOCK_WAIT(OP, FLAGS, PAYLOAD) \
{ \
if (m_psi != NULL) \
{ \
PSI_table_locker *locker; \
PSI_table_locker_state state; \
locker= PSI_TABLE_CALL(start_table_lock_wait) \
(& state, m_psi, OP, FLAGS, \
__FILE__, __LINE__); \
PAYLOAD \
if (locker != NULL) \
PSI_TABLE_CALL(end_table_lock_wait)(locker); \
} \
else \
{ \
PAYLOAD \
} \
}
#else
#define MYSQL_TABLE_LOCK_WAIT(OP, FLAGS, PAYLOAD) \
PAYLOAD
#endif


/*
While we have legacy_db_type, we have this array to
check for dups and to find handlerton from legacy_db_type.
Expand Down Expand Up @@ -1201,7 +1236,8 @@ void ha_pre_shutdown()
times per transaction.
*/
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg,
const ulonglong *trxid)
{
THD_TRANS *trans;
Ha_trx_info *ha_info;
Expand Down Expand Up @@ -1232,6 +1268,25 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
if (thd->transaction.implicit_xid.is_null())
thd->transaction.implicit_xid.set(thd->query_id);

/*
Register transaction start in performance schema if not done already.
By doing this, we handle cases when the transaction is started implicitly in
autocommit=0 mode, and cases when we are in normal autocommit=1 mode and the
executed statement is a single-statement transaction.
Explicitly started transactions are handled in trans_begin().
Do not register transactions in which binary log is the only participating
transactional storage engine.
*/
if (thd->m_transaction_psi == NULL && ht_arg->db_type != DB_TYPE_BINLOG)
{
thd->m_transaction_psi= MYSQL_START_TRANSACTION(&thd->m_transaction_state,
thd->get_xid(), trxid, thd->tx_isolation, thd->tx_read_only,
!thd->in_multi_stmt_transaction_mode());
DEBUG_SYNC(thd, "after_set_transaction_psi_before_set_transaction_gtid");
//gtid_set_performance_schema_values(thd);
}
DBUG_VOID_RETURN;
}

Expand Down Expand Up @@ -1457,7 +1512,11 @@ int ha_commit_trans(THD *thd, bool all)
Free resources and perform other cleanup even for 'empty' transactions.
*/
if (is_real_trans)
{
thd->transaction.cleanup();
MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi);
thd->m_transaction_psi= NULL;
}
#ifdef WITH_WSREP
if (wsrep_is_active(thd) && is_real_trans && !error)
wsrep_commit_empty(thd, all);
Expand Down Expand Up @@ -1651,12 +1710,15 @@ int ha_commit_trans(THD *thd, bool all)
#endif /* WITH_WSREP */
DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE(););
if (tc_log->unlog(cookie, xid))
{
error= 2; /* Error during commit */
goto end;
}

done:
if (is_real_trans)
{
MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi);
thd->m_transaction_psi= NULL;
}

DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););

mysql_mutex_assert_not_owner(&LOCK_prepare_ordered);
Expand Down Expand Up @@ -1694,6 +1756,8 @@ int ha_commit_trans(THD *thd, bool all)
ha_rollback_trans(thd, all);
else
{
MYSQL_ROLLBACK_TRANSACTION(thd->m_transaction_psi);
thd->m_transaction_psi= NULL;
WSREP_DEBUG("rollback skipped %p %d",thd->rgi_slave,
thd->rgi_slave->is_parallel_exec);
}
Expand Down Expand Up @@ -1913,6 +1977,13 @@ int ha_rollback_trans(THD *thd, bool all)
}
(void) wsrep_after_rollback(thd, all);
#endif /* WITH_WSREP */

if (all || !thd->in_active_multi_stmt_transaction())
{
MYSQL_ROLLBACK_TRANSACTION(thd->m_transaction_psi);
thd->m_transaction_psi= NULL;
}

/* Always cleanup. Even if nht==0. There may be savepoints. */
if (is_real_trans)
{
Expand Down Expand Up @@ -2360,6 +2431,10 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
ha_info->reset(); /* keep it conveniently zero-filled */
}
trans->ha_list= sv->ha_list;

if (thd->m_transaction_psi != NULL)
MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(thd->m_transaction_psi, 1);

DBUG_RETURN(error);
}

Expand Down Expand Up @@ -2411,6 +2486,9 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv)
*/
sv->ha_list= trans->ha_list;

if (!error && thd->m_transaction_psi != NULL)
MYSQL_INC_TRANSACTION_SAVEPOINTS(thd->m_transaction_psi, 1);

DBUG_RETURN(error);
}

Expand All @@ -2435,6 +2513,10 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
error=1;
}
}

if (thd->m_transaction_psi != NULL)
MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(thd->m_transaction_psi, 1);

DBUG_RETURN(error);
}

Expand Down
14 changes: 7 additions & 7 deletions sql/log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2212,8 +2212,8 @@ void MYSQL_BIN_LOG::set_write_error(THD *thd, bool is_transactional)
if (WSREP_EMULATE_BINLOG(thd))
{
if (is_transactional)
trans_register_ha(thd, TRUE, binlog_hton);
trans_register_ha(thd, FALSE, binlog_hton);
trans_register_ha(thd, TRUE, binlog_hton, NULL);
trans_register_ha(thd, FALSE, binlog_hton, NULL);
}
#endif /* WITH_WSREP */
DBUG_VOID_RETURN;
Expand Down Expand Up @@ -5713,8 +5713,8 @@ THD::binlog_start_trans_and_stmt()
}
#endif
if (mstmt_mode)
trans_register_ha(this, TRUE, binlog_hton);
trans_register_ha(this, FALSE, binlog_hton);
trans_register_ha(this, TRUE, binlog_hton, NULL);
trans_register_ha(this, FALSE, binlog_hton, NULL);
/*
Mark statement transaction as read/write. We never start
a binary log transaction and keep it read-only,
Expand Down Expand Up @@ -5758,7 +5758,7 @@ binlog_start_consistent_snapshot(handlerton *hton, THD *thd)
strmake_buf(cache_mngr->last_commit_pos_file, mysql_bin_log.last_commit_pos_file);
cache_mngr->last_commit_pos_offset= mysql_bin_log.last_commit_pos_offset;

trans_register_ha(thd, TRUE, hton);
trans_register_ha(thd, TRUE, binlog_hton, NULL);

DBUG_RETURN(err);
}
Expand Down Expand Up @@ -10749,8 +10749,8 @@ void wsrep_register_binlog_handler(THD *thd, bool trx)
Set callbacks in order to be able to call commmit or rollback.
*/
if (trx)
trans_register_ha(thd, TRUE, binlog_hton);
trans_register_ha(thd, FALSE, binlog_hton);
trans_register_ha(thd, TRUE, binlog_hton, NULL);
trans_register_ha(thd, FALSE, binlog_hton, NULL);

/*
Set the binary log as read/write otherwise callbacks are not called.
Expand Down
13 changes: 2 additions & 11 deletions sql/sql_class.cc
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
accessed_rows_and_keys(0),
m_digest(NULL),
m_statement_psi(NULL),
m_transaction_psi(NULL),
m_idle_psi(NULL),
col_access(NO_ACL),
thread_id(id),
Expand Down Expand Up @@ -1189,19 +1190,9 @@ void *thd_memdup(MYSQL_THD thd, const void* str, size_t size)
extern "C"
void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
{
#ifdef WITH_WSREP
if (!thd->wsrep_xid.is_null())
{
*xid = *(MYSQL_XID *) &thd->wsrep_xid;
return;
}
#endif /* WITH_WSREP */
*xid= thd->transaction.xid_state.is_explicit_XA() ?
*(MYSQL_XID *) thd->transaction.xid_state.get_xid() :
*(MYSQL_XID *) &thd->transaction.implicit_xid;
*xid = *(MYSQL_XID *) thd->get_xid();
}


extern "C"
my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime,
unsigned int *errcode)
Expand Down
19 changes: 19 additions & 0 deletions sql/sql_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -3053,6 +3053,14 @@ class THD: public THD_count, /* this must be first */
/** Current statement instrumentation state. */
PSI_statement_locker_state m_statement_state;
#endif /* HAVE_PSI_STATEMENT_INTERFACE */

/** Current transaction instrumentation. */
PSI_transaction_locker *m_transaction_psi;
#ifdef HAVE_PSI_TRANSACTION_INTERFACE
/** Current transaction instrumentation state. */
PSI_transaction_locker_state m_transaction_state;
#endif /* HAVE_PSI_TRANSACTION_INTERFACE */

/** Idle instrumentation. */
PSI_idle_locker *m_idle_psi;
#ifdef HAVE_PSI_IDLE_INTERFACE
Expand Down Expand Up @@ -4819,6 +4827,17 @@ class THD: public THD_count, /* this must be first */
LF_PINS *xid_hash_pins;
bool fix_xid_hash_pins();

const XID *get_xid() const
{
#ifdef WITH_WSREP
if (!wsrep_xid.is_null())
return &wsrep_xid;
#endif /* WITH_WSREP */
return transaction.xid_state.is_explicit_XA() ?
transaction.xid_state.get_xid() :
&transaction.implicit_xid;
}

/* Members related to temporary tables. */
public:
/* Opened table states. */
Expand Down
39 changes: 38 additions & 1 deletion sql/transaction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_acl.h"
#include "semisync_master.h"
#include <pfs_transaction_provider.h>
#include <mysql/psi/mysql_transaction.h>
#ifdef WITH_WSREP
#include "wsrep_trans_observer.h"
#endif /* WITH_WSREP */
Expand Down Expand Up @@ -209,6 +211,23 @@ bool trans_begin(THD *thd, uint flags)
#endif //EMBEDDED_LIBRARY
res= ha_start_consistent_snapshot(thd);
}
/*
Register transaction start in performance schema if not done already.
We handle explicitly started transactions here, implicitly started
transactions (and single-statement transactions in autocommit=1 mode)
are handled in trans_register_ha().
We can't handle explicit transactions in the same way as implicit
because we want to correctly attribute statements which follow
BEGIN but do not touch any transactional tables.
*/
if (thd->m_transaction_psi == NULL)
{
thd->m_transaction_psi= MYSQL_START_TRANSACTION(&thd->m_transaction_state,
NULL, NULL, thd->tx_isolation,
thd->tx_read_only, false);
DEBUG_SYNC(thd, "after_set_transaction_psi_before_set_transaction_gtid");
//gtid_set_performance_schema_values(thd);
}

DBUG_RETURN(MY_TEST(res));
}
Expand Down Expand Up @@ -255,6 +274,8 @@ bool trans_commit(THD *thd)
thd->transaction.all.reset();
thd->lex->start_transaction_opt= 0;

/* The transaction should be marked as complete in P_S. */
DBUG_ASSERT(thd->m_transaction_psi == NULL);
trans_track_end_trx(thd);

DBUG_RETURN(MY_TEST(res));
Expand Down Expand Up @@ -299,6 +320,9 @@ bool trans_commit_implicit(THD *thd)
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.reset();

/* The transaction should be marked as complete in P_S. */
DBUG_ASSERT(thd->m_transaction_psi == NULL);

/*
Upon implicit commit, reset the current transaction
isolation level and access mode. We do not care about
Expand Down Expand Up @@ -343,6 +367,9 @@ bool trans_rollback(THD *thd)
thd->transaction.all.reset();
thd->lex->start_transaction_opt= 0;

/* The transaction should be marked as complete in P_S. */
DBUG_ASSERT(thd->m_transaction_psi == NULL);

trans_track_end_trx(thd);

DBUG_RETURN(MY_TEST(res));
Expand Down Expand Up @@ -389,7 +416,9 @@ bool trans_rollback_implicit(THD *thd)
thd->transaction.all.reset();

/* Rollback should clear transaction_rollback_request flag. */
DBUG_ASSERT(! thd->transaction_rollback_request);
DBUG_ASSERT(!thd->transaction_rollback_request);
/* The transaction should be marked as complete in P_S. */
DBUG_ASSERT(thd->m_transaction_psi == NULL);

trans_track_end_trx(thd);

Expand Down Expand Up @@ -457,6 +486,10 @@ bool trans_commit_stmt(THD *thd)
#endif
}

/* In autocommit=1 mode the transaction should be marked as complete in P_S */
DBUG_ASSERT(thd->in_active_multi_stmt_transaction() ||
thd->m_transaction_psi == NULL);

thd->transaction.stmt.reset();

DBUG_RETURN(MY_TEST(res));
Expand Down Expand Up @@ -496,6 +529,10 @@ bool trans_rollback_stmt(THD *thd)
repl_semisync_master.wait_after_rollback(thd, FALSE);
#endif

/* In autocommit=1 mode the transaction should be marked as complete in P_S */
DBUG_ASSERT(thd->in_active_multi_stmt_transaction() ||
thd->m_transaction_psi == NULL);

thd->transaction.stmt.reset();

DBUG_RETURN(FALSE);
Expand Down
Loading

0 comments on commit 81cffda

Please sign in to comment.