events_transactions_current是performance_schema中记录事务状态信息的表,它除了可以记录普通事务以外,还可以记录MySQL中的XA事务。
表结构如下:
mysql> show create table performance_schema.events_transactions_current\G
*************************** 1. row ***************************
Table: events_transactions_current
Create Table: CREATE TABLE `events_transactions_current` (
`THREAD_ID` bigint(20) unsigned NOT NULL,
`EVENT_ID` bigint(20) unsigned NOT NULL,
`END_EVENT_ID` bigint(20) unsigned DEFAULT NULL,
`EVENT_NAME` varchar(128) NOT NULL,
`STATE` enum('ACTIVE','COMMITTED','ROLLED BACK') DEFAULT NULL,
`TRX_ID` bigint(20) unsigned DEFAULT NULL,
`GTID` varchar(64) DEFAULT NULL,
`XID_FORMAT_ID` int(11) DEFAULT NULL,
`XID_GTRID` varchar(130) DEFAULT NULL,
`XID_BQUAL` varchar(130) DEFAULT NULL,
`XA_STATE` varchar(64) DEFAULT NULL,
`SOURCE` varchar(64) DEFAULT NULL,
`TIMER_START` bigint(20) unsigned DEFAULT NULL,
`TIMER_END` bigint(20) unsigned DEFAULT NULL,
`TIMER_WAIT` bigint(20) unsigned DEFAULT NULL,
`ACCESS_MODE` enum('READ ONLY','READ WRITE') DEFAULT NULL,
`ISOLATION_LEVEL` varchar(64) DEFAULT NULL,
`AUTOCOMMIT` enum('YES','NO') NOT NULL,
`NUMBER_OF_SAVEPOINTS` bigint(20) unsigned DEFAULT NULL,
`NUMBER_OF_ROLLBACK_TO_SAVEPOINT` bigint(20) unsigned DEFAULT NULL,
`NUMBER_OF_RELEASE_SAVEPOINT` bigint(20) unsigned DEFAULT NULL,
`OBJECT_INSTANCE_BEGIN` bigint(20) unsigned DEFAULT NULL,
`NESTING_EVENT_ID` bigint(20) unsigned DEFAULT NULL,
`NESTING_EVENT_TYPE` enum('TRANSACTION','STATEMENT','STAGE','WAIT') DEFAULT NULL
) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
总共有24个字段。
此表对应performance_schema存储引擎的struct row_events_transactions,如下 :
/** A row of table_events_transactions_common. */
struct row_events_transactions
{
/** Column THREAD_ID. */
ulonglong m_thread_internal_id;
/** Column EVENT_ID. */
ulonglong m_event_id;
/** Column END_EVENT_ID. */
ulonglong m_end_event_id;
/** Column NESTING_EVENT_ID. */
ulonglong m_nesting_event_id;
/** Column NESTING_EVENT_TYPE. */
enum_event_type m_nesting_event_type;
/** Column EVENT_NAME. */
const char *m_name;
/** Length in bytes of @c m_name. */
uint m_name_length;
/** Column TIMER_START. */
ulonglong m_timer_start;
/** Column TIMER_END. */
ulonglong m_timer_end;
/** Column TIMER_WAIT. */
ulonglong m_timer_wait;
/** Column SOURCE. */
char m_source[COL_SOURCE_SIZE];
/** Length in bytes of @c m_source. */
uint m_source_length;
/** InnoDB transaction id. */
ulonglong m_trxid;
/** Transaction state. */
enum_transaction_state m_state;
/** Global Transaction ID. */
char m_gtid[Gtid_specification::MAX_TEXT_LENGTH + 1];
/** GTID length in bytes*/
int m_gtid_length;
/** XA transaction ID. */
PSI_xid m_xid;
/** XA transaction state. */
enum_xa_transaction_state m_xa_state;
/** True if XA transaction. */
bool m_xa;
/** True if autocommit transaction. */
bool m_autocommit;
/** Isolation level. */
enum_isolation_level m_isolation_level;
/** True if read-only, read-write otherwise. */
bool m_read_only;
/** Column NUMBER_OF_SAVEPOINTS. */
ulonglong m_savepoint_count;
/** Column NUMBER_OF_ROLLBACK_TO_SAVEPOINT. */
ulonglong m_rollback_to_savepoint_count;
/** Column NUMBER_OF_RELEASE_SAVEPOINT. */
ulonglong m_release_savepoint_count;
};
row_events_transactions的信息由每一个客户端线程独立维护,如下:
class THD :public MDL_context_owner,
public Query_arena,
public Open_tables_state
{
...
/** Current transaction instrumentation. */
PSI_transaction_locker *m_transaction_psi;
...
}
但是m_transaction_psi只记录了如下信息,并没有覆盖到row_events_transactions的所有信息,:
/** A transaction record. */
struct PFS_events_transactions : public PFS_events
{
/** Source identifier, mapped from internal format. */
rpl_sid m_sid;
/** InnoDB transaction ID. */
ulonglong m_trxid;
/** Status */
enum_transaction_state m_state;
/** Global Transaction ID specifier. */
Gtid_specification m_gtid_spec;
/** True if XA transaction. */
my_bool m_xa;
/** XA transaction ID. */
PSI_xid m_xid;
/** XA status */
enum_xa_transaction_state m_xa_state;
/** Transaction isolation level. */
enum_isolation_level m_isolation_level;
/** True if read-only transaction, otherwise read-write. */
my_bool m_read_only;
/** True if autocommit transaction. */
my_bool m_autocommit;
/** Total number of savepoints. */
ulonglong m_savepoint_count;
/** Number of rollback_to_savepoint. */
ulonglong m_rollback_to_savepoint_count;
/** Number of release_savepoint. */
ulonglong m_release_savepoint_count;
};
其它信息比如表示m_timer_end是在由用户查询此表时计算的。
当我们开启监控时,需要对m_transaction_psi进行写入,其过程如下:
...
Sql_cmd_xa_start::execute(THD*)
Sql_cmd_xa_start::trans_xa_start(THD*)
inline_mysql_set_transaction_xid(PSI_transaction_locker*, void const*, int)
::pfs_set_transaction_xid_v1(PSI_transaction_locker *, const void *, int)
函数pfs_set_transaction_xid_v1的主要作用是写入事务的xid,实现如下:
void pfs_set_transaction_xid_v1(PSI_transaction_locker *locker,
const void *xid,
int xa_state)
{
PSI_transaction_locker_state *state= reinterpret_cast<PSI_transaction_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
if (state->m_flags & STATE_FLAG_EVENT)
{
PFS_events_transactions *pfs= reinterpret_cast<PFS_events_transactions*> (state->m_transaction);
DBUG_ASSERT(pfs != NULL);
DBUG_ASSERT(xid != NULL);
pfs->m_xid= *(PSI_xid *)xid;
pfs->m_xa_state= (enum_xa_transaction_state)xa_state;
pfs->m_xa= true;
}
return;
}
下面来看下查询的过程:
handle_query(THD*, LEX*, Query_result*, unsigned long long, unsigned long long)
...
handler::ha_rnd_next(unsigned char*)
ha_perfschema::rnd_next(unsigned char*)
table_events_transactions_current::rnd_next()
table_events_transactions_common::make_row(PFS_events_transactions*)
通过table_events_transactions_common::make_row(PFS_events_transactions *transaction)函数根据PSI_transaction_locker中的信息生成行数据返回给客户端,感兴趣的读者可以继续阅读函数table_events_transactions_common::make_row(PFS_events_transactions *transaction)。