create definer = `mysql.sys`@localhost function sys.ps_thread_trx_info(in_thread_id bigint unsigned) returns longtext comment ' Description ----------- Returns a JSON object with info on the given threads current transaction, and the statements it has already executed, derived from the performance_schema.events_transactions_current and performance_schema.events_statements_history tables (so the consumers for these also have to be enabled within Performance Schema to get full data in the object). When the output exceeds the default truncation length (65535), a JSON error object is returned, such as: { "error": "Trx info truncated: Row 6 was cut by GROUP_CONCAT()" } Similar error objects are returned for other warnings/and exceptions raised when calling the function. The max length of the output of this function can be controlled with the ps_thread_trx_info.max_length variable set via sys_config, or the @sys.ps_thread_trx_info.max_length user variable, as appropriate. Parameters ----------- in_thread_id (BIGINT UNSIGNED): The id of the thread to return the transaction info for. Example ----------- SELECT sys.ps_thread_trx_info(48)\G *************************** 1. row *************************** sys.ps_thread_trx_info(48): [ { "time": "790.70 us", "state": "COMMITTED", "mode": "READ WRITE", "autocommitted": "NO", "gtid": "AUTOMATIC", "isolation": "REPEATABLE READ", "statements_executed": [ { "sql_text": "INSERT INTO info VALUES (1, ''foo'')", "time": "471.02 us", "schema": "trx", "rows_examined": 0, "rows_affected": 1, "rows_sent": 0, "tmp_tables": 0, "tmp_disk_tables": 0, "sort_rows": 0, "sort_merge_passes": 0 }, { "sql_text": "COMMIT", "time": "254.42 us", "schema": "trx", "rows_examined": 0, "rows_affected": 0, "rows_sent": 0, "tmp_tables": 0, "tmp_disk_tables": 0, "sort_rows": 0, "sort_merge_passes": 0 } ] }, { "time": "426.20 us", "state": "COMMITTED", "mode": "READ WRITE", "autocommitted": "NO", "gtid": "AUTOMATIC", "isolation": "REPEATABLE READ", "statements_executed": [ { "sql_text": "INSERT INTO info VALUES (2, ''bar'')", "time": "107.33 us", "schema": "trx", "rows_examined": 0, "rows_affected": 1, "rows_sent": 0, "tmp_tables": 0, "tmp_disk_tables": 0, "sort_rows": 0, "sort_merge_passes": 0 }, { "sql_text": "COMMIT", "time": "213.23 us", "schema": "trx", "rows_examined": 0, "rows_affected": 0, "rows_sent": 0, "tmp_tables": 0, "tmp_disk_tables": 0, "sort_rows": 0, "sort_merge_passes": 0 } ] } ] 1 row in set (0.03 sec) ' sql security invoker reads sql data BEGIN DECLARE v_output LONGTEXT DEFAULT '{}'; DECLARE v_msg_text TEXT DEFAULT ''; DECLARE v_signal_msg TEXT DEFAULT ''; DECLARE v_mysql_errno INT; DECLARE v_max_output_len BIGINT; -- Capture warnings/errors such as group_concat truncation -- and report as JSON error objects DECLARE EXIT HANDLER FOR SQLWARNING, SQLEXCEPTION BEGIN GET DIAGNOSTICS CONDITION 1 v_msg_text = MESSAGE_TEXT, v_mysql_errno = MYSQL_ERRNO; IF v_mysql_errno = 1260 THEN SET v_signal_msg = CONCAT('{ "error": "Trx info truncated: ', v_msg_text, '" }'); ELSE SET v_signal_msg = CONCAT('{ "error": "', v_msg_text, '" }'); END IF; RETURN v_signal_msg; END; -- Set configuration options IF (@sys.ps_thread_trx_info.max_length IS NULL) THEN SET @sys.ps_thread_trx_info.max_length = sys.sys_get_config('ps_thread_trx_info.max_length', 65535); END IF; IF (@sys.ps_thread_trx_info.max_length != @@session.group_concat_max_len) THEN SET @old_group_concat_max_len = @@session.group_concat_max_len; -- Convert to int value for the SET, and give some surrounding space SET v_max_output_len = (@sys.ps_thread_trx_info.max_length - 5); SET SESSION group_concat_max_len = v_max_output_len; END IF; SET v_output = ( SELECT CONCAT('[', IFNULL(GROUP_CONCAT(trx_info ORDER BY event_id), ''), '\n]') AS trx_info FROM (SELECT trxi.thread_id, trxi.event_id, GROUP_CONCAT( IFNULL( CONCAT('\n {\n', ' "time": "', IFNULL(format_pico_time(trxi.timer_wait), ''), '",\n', ' "state": "', IFNULL(trxi.state, ''), '",\n', ' "mode": "', IFNULL(trxi.access_mode, ''), '",\n', ' "autocommitted": "', IFNULL(trxi.autocommit, ''), '",\n', ' "gtid": "', IFNULL(trxi.gtid, ''), '",\n', ' "isolation": "', IFNULL(trxi.isolation_level, ''), '",\n', ' "statements_executed": [', IFNULL(s.stmts, ''), IF(s.stmts IS NULL, ' ]\n', '\n ]\n'), ' }' ), '') ORDER BY event_id) AS trx_info FROM ( (SELECT thread_id, event_id, timer_wait, state,access_mode, autocommit, gtid, isolation_level FROM performance_schema.events_transactions_current WHERE thread_id = in_thread_id AND end_event_id IS NULL) UNION (SELECT thread_id, event_id, timer_wait, state,access_mode, autocommit, gtid, isolation_level FROM performance_schema.events_transactions_history WHERE thread_id = in_thread_id) ) AS trxi LEFT JOIN (SELECT thread_id, nesting_event_id, GROUP_CONCAT( IFNULL( CONCAT('\n {\n', ' "sql_text": "', IFNULL(sys.format_statement(REPLACE(sql_text, '\\', '\\\\')), ''), '",\n', ' "time": "', IFNULL(format_pico_time(timer_wait), ''), '",\n', ' "schema": "', IFNULL(current_schema, ''), '",\n', ' "rows_examined": ', IFNULL(rows_examined, ''), ',\n', ' "rows_affected": ', IFNULL(rows_affected, ''), ',\n', ' "rows_sent": ', IFNULL(rows_sent, ''), ',\n', ' "tmp_tables": ', IFNULL(created_tmp_tables, ''), ',\n', ' "tmp_disk_tables": ', IFNULL(created_tmp_disk_tables, ''), ',\n', ' "sort_rows": ', IFNULL(sort_rows, ''), ',\n', ' "sort_merge_passes": ', IFNULL(sort_merge_passes, ''), '\n', ' }'), '') ORDER BY event_id) AS stmts FROM performance_schema.events_statements_history WHERE sql_text IS NOT NULL AND thread_id = in_thread_id GROUP BY thread_id, nesting_event_id ) AS s ON trxi.thread_id = s.thread_id AND trxi.event_id = s.nesting_event_id WHERE trxi.thread_id = in_thread_id GROUP BY trxi.thread_id, trxi.event_id ) trxs GROUP BY thread_id ); IF (@old_group_concat_max_len IS NOT NULL) THEN SET SESSION group_concat_max_len = @old_group_concat_max_len; END IF; RETURN v_output; END;