Skip to content

Commit 81cffda

Browse files
committed
perfschema transaction instrumentation related changes
1 parent 6ded554 commit 81cffda

File tree

10 files changed

+188
-41
lines changed

10 files changed

+188
-41
lines changed

sql/handler.cc

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#include "myisam.h"
4141
#include "probes_mysql.h"
4242
#include <mysql/psi/mysql_table.h>
43+
#include <pfs_transaction_provider.h>
44+
#include <mysql/psi/mysql_transaction.h>
4345
#include "debug_sync.h" // DEBUG_SYNC
4446
#include "sql_audit.h"
4547
#include "ha_sequence.h"
@@ -62,6 +64,39 @@
6264
#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
6365
#endif /* WITH_WSREP */
6466

67+
/**
68+
@def MYSQL_TABLE_LOCK_WAIT
69+
Instrumentation helper for table io_waits.
70+
@param OP the table operation to be performed
71+
@param FLAGS per table operation flags.
72+
@param PAYLOAD the code to instrument.
73+
@sa MYSQL_END_TABLE_WAIT.
74+
*/
75+
#ifdef HAVE_PSI_TABLE_INTERFACE
76+
#define MYSQL_TABLE_LOCK_WAIT(OP, FLAGS, PAYLOAD) \
77+
{ \
78+
if (m_psi != NULL) \
79+
{ \
80+
PSI_table_locker *locker; \
81+
PSI_table_locker_state state; \
82+
locker= PSI_TABLE_CALL(start_table_lock_wait) \
83+
(& state, m_psi, OP, FLAGS, \
84+
__FILE__, __LINE__); \
85+
PAYLOAD \
86+
if (locker != NULL) \
87+
PSI_TABLE_CALL(end_table_lock_wait)(locker); \
88+
} \
89+
else \
90+
{ \
91+
PAYLOAD \
92+
} \
93+
}
94+
#else
95+
#define MYSQL_TABLE_LOCK_WAIT(OP, FLAGS, PAYLOAD) \
96+
PAYLOAD
97+
#endif
98+
99+
65100
/*
66101
While we have legacy_db_type, we have this array to
67102
check for dups and to find handlerton from legacy_db_type.
@@ -1201,7 +1236,8 @@ void ha_pre_shutdown()
12011236
times per transaction.
12021237
12031238
*/
1204-
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
1239+
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg,
1240+
const ulonglong *trxid)
12051241
{
12061242
THD_TRANS *trans;
12071243
Ha_trx_info *ha_info;
@@ -1232,6 +1268,25 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
12321268
if (thd->transaction.implicit_xid.is_null())
12331269
thd->transaction.implicit_xid.set(thd->query_id);
12341270

1271+
/*
1272+
Register transaction start in performance schema if not done already.
1273+
By doing this, we handle cases when the transaction is started implicitly in
1274+
autocommit=0 mode, and cases when we are in normal autocommit=1 mode and the
1275+
executed statement is a single-statement transaction.
1276+
1277+
Explicitly started transactions are handled in trans_begin().
1278+
1279+
Do not register transactions in which binary log is the only participating
1280+
transactional storage engine.
1281+
*/
1282+
if (thd->m_transaction_psi == NULL && ht_arg->db_type != DB_TYPE_BINLOG)
1283+
{
1284+
thd->m_transaction_psi= MYSQL_START_TRANSACTION(&thd->m_transaction_state,
1285+
thd->get_xid(), trxid, thd->tx_isolation, thd->tx_read_only,
1286+
!thd->in_multi_stmt_transaction_mode());
1287+
DEBUG_SYNC(thd, "after_set_transaction_psi_before_set_transaction_gtid");
1288+
//gtid_set_performance_schema_values(thd);
1289+
}
12351290
DBUG_VOID_RETURN;
12361291
}
12371292

@@ -1457,7 +1512,11 @@ int ha_commit_trans(THD *thd, bool all)
14571512
Free resources and perform other cleanup even for 'empty' transactions.
14581513
*/
14591514
if (is_real_trans)
1515+
{
14601516
thd->transaction.cleanup();
1517+
MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi);
1518+
thd->m_transaction_psi= NULL;
1519+
}
14611520
#ifdef WITH_WSREP
14621521
if (wsrep_is_active(thd) && is_real_trans && !error)
14631522
wsrep_commit_empty(thd, all);
@@ -1651,12 +1710,15 @@ int ha_commit_trans(THD *thd, bool all)
16511710
#endif /* WITH_WSREP */
16521711
DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE(););
16531712
if (tc_log->unlog(cookie, xid))
1654-
{
16551713
error= 2; /* Error during commit */
1656-
goto end;
1657-
}
16581714

16591715
done:
1716+
if (is_real_trans)
1717+
{
1718+
MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi);
1719+
thd->m_transaction_psi= NULL;
1720+
}
1721+
16601722
DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););
16611723

16621724
mysql_mutex_assert_not_owner(&LOCK_prepare_ordered);
@@ -1694,6 +1756,8 @@ int ha_commit_trans(THD *thd, bool all)
16941756
ha_rollback_trans(thd, all);
16951757
else
16961758
{
1759+
MYSQL_ROLLBACK_TRANSACTION(thd->m_transaction_psi);
1760+
thd->m_transaction_psi= NULL;
16971761
WSREP_DEBUG("rollback skipped %p %d",thd->rgi_slave,
16981762
thd->rgi_slave->is_parallel_exec);
16991763
}
@@ -1913,6 +1977,13 @@ int ha_rollback_trans(THD *thd, bool all)
19131977
}
19141978
(void) wsrep_after_rollback(thd, all);
19151979
#endif /* WITH_WSREP */
1980+
1981+
if (all || !thd->in_active_multi_stmt_transaction())
1982+
{
1983+
MYSQL_ROLLBACK_TRANSACTION(thd->m_transaction_psi);
1984+
thd->m_transaction_psi= NULL;
1985+
}
1986+
19161987
/* Always cleanup. Even if nht==0. There may be savepoints. */
19171988
if (is_real_trans)
19181989
{
@@ -2360,6 +2431,10 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
23602431
ha_info->reset(); /* keep it conveniently zero-filled */
23612432
}
23622433
trans->ha_list= sv->ha_list;
2434+
2435+
if (thd->m_transaction_psi != NULL)
2436+
MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(thd->m_transaction_psi, 1);
2437+
23632438
DBUG_RETURN(error);
23642439
}
23652440

@@ -2411,6 +2486,9 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv)
24112486
*/
24122487
sv->ha_list= trans->ha_list;
24132488

2489+
if (!error && thd->m_transaction_psi != NULL)
2490+
MYSQL_INC_TRANSACTION_SAVEPOINTS(thd->m_transaction_psi, 1);
2491+
24142492
DBUG_RETURN(error);
24152493
}
24162494

@@ -2435,6 +2513,10 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
24352513
error=1;
24362514
}
24372515
}
2516+
2517+
if (thd->m_transaction_psi != NULL)
2518+
MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(thd->m_transaction_psi, 1);
2519+
24382520
DBUG_RETURN(error);
24392521
}
24402522

sql/log.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,8 +2212,8 @@ void MYSQL_BIN_LOG::set_write_error(THD *thd, bool is_transactional)
22122212
if (WSREP_EMULATE_BINLOG(thd))
22132213
{
22142214
if (is_transactional)
2215-
trans_register_ha(thd, TRUE, binlog_hton);
2216-
trans_register_ha(thd, FALSE, binlog_hton);
2215+
trans_register_ha(thd, TRUE, binlog_hton, NULL);
2216+
trans_register_ha(thd, FALSE, binlog_hton, NULL);
22172217
}
22182218
#endif /* WITH_WSREP */
22192219
DBUG_VOID_RETURN;
@@ -5713,8 +5713,8 @@ THD::binlog_start_trans_and_stmt()
57135713
}
57145714
#endif
57155715
if (mstmt_mode)
5716-
trans_register_ha(this, TRUE, binlog_hton);
5717-
trans_register_ha(this, FALSE, binlog_hton);
5716+
trans_register_ha(this, TRUE, binlog_hton, NULL);
5717+
trans_register_ha(this, FALSE, binlog_hton, NULL);
57185718
/*
57195719
Mark statement transaction as read/write. We never start
57205720
a binary log transaction and keep it read-only,
@@ -5758,7 +5758,7 @@ binlog_start_consistent_snapshot(handlerton *hton, THD *thd)
57585758
strmake_buf(cache_mngr->last_commit_pos_file, mysql_bin_log.last_commit_pos_file);
57595759
cache_mngr->last_commit_pos_offset= mysql_bin_log.last_commit_pos_offset;
57605760

5761-
trans_register_ha(thd, TRUE, hton);
5761+
trans_register_ha(thd, TRUE, binlog_hton, NULL);
57625762

57635763
DBUG_RETURN(err);
57645764
}
@@ -10749,8 +10749,8 @@ void wsrep_register_binlog_handler(THD *thd, bool trx)
1074910749
Set callbacks in order to be able to call commmit or rollback.
1075010750
*/
1075110751
if (trx)
10752-
trans_register_ha(thd, TRUE, binlog_hton);
10753-
trans_register_ha(thd, FALSE, binlog_hton);
10752+
trans_register_ha(thd, TRUE, binlog_hton, NULL);
10753+
trans_register_ha(thd, FALSE, binlog_hton, NULL);
1075410754

1075510755
/*
1075610756
Set the binary log as read/write otherwise callbacks are not called.

sql/sql_class.cc

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
643643
accessed_rows_and_keys(0),
644644
m_digest(NULL),
645645
m_statement_psi(NULL),
646+
m_transaction_psi(NULL),
646647
m_idle_psi(NULL),
647648
col_access(NO_ACL),
648649
thread_id(id),
@@ -1189,19 +1190,9 @@ void *thd_memdup(MYSQL_THD thd, const void* str, size_t size)
11891190
extern "C"
11901191
void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
11911192
{
1192-
#ifdef WITH_WSREP
1193-
if (!thd->wsrep_xid.is_null())
1194-
{
1195-
*xid = *(MYSQL_XID *) &thd->wsrep_xid;
1196-
return;
1197-
}
1198-
#endif /* WITH_WSREP */
1199-
*xid= thd->transaction.xid_state.is_explicit_XA() ?
1200-
*(MYSQL_XID *) thd->transaction.xid_state.get_xid() :
1201-
*(MYSQL_XID *) &thd->transaction.implicit_xid;
1193+
*xid = *(MYSQL_XID *) thd->get_xid();
12021194
}
12031195

1204-
12051196
extern "C"
12061197
my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime,
12071198
unsigned int *errcode)

sql/sql_class.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,14 @@ class THD: public THD_count, /* this must be first */
30533053
/** Current statement instrumentation state. */
30543054
PSI_statement_locker_state m_statement_state;
30553055
#endif /* HAVE_PSI_STATEMENT_INTERFACE */
3056+
3057+
/** Current transaction instrumentation. */
3058+
PSI_transaction_locker *m_transaction_psi;
3059+
#ifdef HAVE_PSI_TRANSACTION_INTERFACE
3060+
/** Current transaction instrumentation state. */
3061+
PSI_transaction_locker_state m_transaction_state;
3062+
#endif /* HAVE_PSI_TRANSACTION_INTERFACE */
3063+
30563064
/** Idle instrumentation. */
30573065
PSI_idle_locker *m_idle_psi;
30583066
#ifdef HAVE_PSI_IDLE_INTERFACE
@@ -4819,6 +4827,17 @@ class THD: public THD_count, /* this must be first */
48194827
LF_PINS *xid_hash_pins;
48204828
bool fix_xid_hash_pins();
48214829

4830+
const XID *get_xid() const
4831+
{
4832+
#ifdef WITH_WSREP
4833+
if (!wsrep_xid.is_null())
4834+
return &wsrep_xid;
4835+
#endif /* WITH_WSREP */
4836+
return transaction.xid_state.is_explicit_XA() ?
4837+
transaction.xid_state.get_xid() :
4838+
&transaction.implicit_xid;
4839+
}
4840+
48224841
/* Members related to temporary tables. */
48234842
public:
48244843
/* Opened table states. */

sql/transaction.cc

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "debug_sync.h" // DEBUG_SYNC
2626
#include "sql_acl.h"
2727
#include "semisync_master.h"
28+
#include <pfs_transaction_provider.h>
29+
#include <mysql/psi/mysql_transaction.h>
2830
#ifdef WITH_WSREP
2931
#include "wsrep_trans_observer.h"
3032
#endif /* WITH_WSREP */
@@ -209,6 +211,23 @@ bool trans_begin(THD *thd, uint flags)
209211
#endif //EMBEDDED_LIBRARY
210212
res= ha_start_consistent_snapshot(thd);
211213
}
214+
/*
215+
Register transaction start in performance schema if not done already.
216+
We handle explicitly started transactions here, implicitly started
217+
transactions (and single-statement transactions in autocommit=1 mode)
218+
are handled in trans_register_ha().
219+
We can't handle explicit transactions in the same way as implicit
220+
because we want to correctly attribute statements which follow
221+
BEGIN but do not touch any transactional tables.
222+
*/
223+
if (thd->m_transaction_psi == NULL)
224+
{
225+
thd->m_transaction_psi= MYSQL_START_TRANSACTION(&thd->m_transaction_state,
226+
NULL, NULL, thd->tx_isolation,
227+
thd->tx_read_only, false);
228+
DEBUG_SYNC(thd, "after_set_transaction_psi_before_set_transaction_gtid");
229+
//gtid_set_performance_schema_values(thd);
230+
}
212231

213232
DBUG_RETURN(MY_TEST(res));
214233
}
@@ -255,6 +274,8 @@ bool trans_commit(THD *thd)
255274
thd->transaction.all.reset();
256275
thd->lex->start_transaction_opt= 0;
257276

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

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

323+
/* The transaction should be marked as complete in P_S. */
324+
DBUG_ASSERT(thd->m_transaction_psi == NULL);
325+
302326
/*
303327
Upon implicit commit, reset the current transaction
304328
isolation level and access mode. We do not care about
@@ -343,6 +367,9 @@ bool trans_rollback(THD *thd)
343367
thd->transaction.all.reset();
344368
thd->lex->start_transaction_opt= 0;
345369

370+
/* The transaction should be marked as complete in P_S. */
371+
DBUG_ASSERT(thd->m_transaction_psi == NULL);
372+
346373
trans_track_end_trx(thd);
347374

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

391418
/* Rollback should clear transaction_rollback_request flag. */
392-
DBUG_ASSERT(! thd->transaction_rollback_request);
419+
DBUG_ASSERT(!thd->transaction_rollback_request);
420+
/* The transaction should be marked as complete in P_S. */
421+
DBUG_ASSERT(thd->m_transaction_psi == NULL);
393422

394423
trans_track_end_trx(thd);
395424

@@ -457,6 +486,10 @@ bool trans_commit_stmt(THD *thd)
457486
#endif
458487
}
459488

489+
/* In autocommit=1 mode the transaction should be marked as complete in P_S */
490+
DBUG_ASSERT(thd->in_active_multi_stmt_transaction() ||
491+
thd->m_transaction_psi == NULL);
492+
460493
thd->transaction.stmt.reset();
461494

462495
DBUG_RETURN(MY_TEST(res));
@@ -496,6 +529,10 @@ bool trans_rollback_stmt(THD *thd)
496529
repl_semisync_master.wait_after_rollback(thd, FALSE);
497530
#endif
498531

532+
/* In autocommit=1 mode the transaction should be marked as complete in P_S */
533+
DBUG_ASSERT(thd->in_active_multi_stmt_transaction() ||
534+
thd->m_transaction_psi == NULL);
535+
499536
thd->transaction.stmt.reset();
500537

501538
DBUG_RETURN(FALSE);

0 commit comments

Comments
 (0)