mariadb/storage/innobase/handler/i_s.cc
Gopal Shankar 119984db0c Bug#18776592 INNODB: FAILING ASSERTION: PRIMARY_KEY_NO == -1 ||
PRIMARY_KEY_NO == 0 

This bug is a backport of the following revision of 5.6 source tree:
# committer: Gopal Shankar <gopal.shankar@oracle.com>
# branch nick: priKey56
# timestamp: Wed 2013-05-29 11:11:46 +0530
# message:
#   Bug#16368875 INNODB: FAILING ASSERTION:
2014-06-25 09:50:17 +05:30

3702 lines
105 KiB
C++

/*****************************************************************************
Copyright (c) 2007, 2013, Innobase Oy. All Rights Reserved.
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
*****************************************************************************/
/**************************************************//**
@file handler/i_s.cc
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
*******************************************************/
#include <mysqld_error.h>
#include <sql_acl.h>
#include <m_ctype.h>
#include <hash.h>
#include <myisampack.h>
#include <mysys_err.h>
#include <my_sys.h>
#include "i_s.h"
#include <sql_plugin.h>
#include <mysql/innodb_priv.h>
extern "C" {
#include "btr0types.h"
#include "buf0buddy.h"
#include "buf0buf.h"
#include "ibuf0ibuf.h"
#include "dict0mem.h"
#include "dict0types.h"
#include "dict0boot.h"
#include "ha_prototypes.h"
#include "srv0start.h"
#include "trx0i_s.h"
#include "trx0trx.h"
#include "btr0btr.h"
#include "page0zip.h"
#include "log0log.h"
}
/** structure associates a name string with a file page type and/or buffer
page state. */
struct buffer_page_desc_str_struct{
const char* type_str; /*!< String explain the page
type/state */
ulint type_value; /*!< Page type or page state */
};
typedef struct buffer_page_desc_str_struct buf_page_desc_str_t;
/** Change buffer B-tree page */
#define I_S_PAGE_TYPE_IBUF (FIL_PAGE_TYPE_LAST + 1)
/** Any states greater than I_S_PAGE_TYPE_IBUF would be treated as
unknown. */
#define I_S_PAGE_TYPE_UNKNOWN (I_S_PAGE_TYPE_IBUF + 1)
/** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position
in i_s_page_type[] array */
#define I_S_PAGE_TYPE_INDEX 1
/** Name string for File Page Types */
static buf_page_desc_str_t i_s_page_type[] = {
{"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED},
{"INDEX", FIL_PAGE_INDEX},
{"UNDO_LOG", FIL_PAGE_UNDO_LOG},
{"INODE", FIL_PAGE_INODE},
{"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST},
{"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP},
{"SYSTEM", FIL_PAGE_TYPE_SYS},
{"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS},
{"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR},
{"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES},
{"BLOB", FIL_PAGE_TYPE_BLOB},
{"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB},
{"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2},
{"IBUF_INDEX", I_S_PAGE_TYPE_IBUF},
{"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN}
};
/* Check if we can hold all page type in a 4 bit value */
#if I_S_PAGE_TYPE_UNKNOWN > 1<<4
# error "i_s_page_type[] is too large"
#endif
/** This structure defines information we will fetch from pages
currently cached in the buffer pool. It will be used to populate
table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */
struct buffer_page_info_struct{
ulint block_id; /*!< Buffer Pool block ID */
unsigned space_id:32; /*!< Tablespace ID */
unsigned page_num:32; /*!< Page number/offset */
unsigned access_time:32; /*!< Time of first access */
unsigned pool_id:MAX_BUFFER_POOLS_BITS;
/*!< Buffer Pool ID. Must be less than
MAX_BUFFER_POOLS */
unsigned flush_type:2; /*!< Flush type */
unsigned io_fix:2; /*!< type of pending I/O operation */
unsigned fix_count:19; /*!< Count of how manyfold this block
is bufferfixed */
unsigned hashed:1; /*!< Whether hash index has been
built on this page */
unsigned is_old:1; /*!< TRUE if the block is in the old
blocks in buf_pool->LRU_old */
unsigned freed_page_clock:31; /*!< the value of
buf_pool->freed_page_clock */
unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS;
/*!< Compressed page size */
unsigned page_state:BUF_PAGE_STATE_BITS; /*!< Page state */
unsigned page_type:4; /*!< Page type */
unsigned num_recs:UNIV_PAGE_SIZE_SHIFT-2;
/*!< Number of records on Page */
unsigned data_size:UNIV_PAGE_SIZE_SHIFT;
/*!< Sum of the sizes of the records */
lsn_t newest_mod; /*!< Log sequence number of
the youngest modification */
lsn_t oldest_mod; /*!< Log sequence number of
the oldest modification */
index_id_t index_id; /*!< Index ID if a index page */
};
typedef struct buffer_page_info_struct buf_page_info_t;
/** maximum number of buffer page info we would cache. */
#define MAX_BUF_INFO_CACHED 10000
#define OK(expr) \
if ((expr) != 0) { \
DBUG_RETURN(1); \
}
#define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \
do { \
if (!srv_was_started) { \
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, \
ER_CANT_FIND_SYSTEM_REC, \
"InnoDB: SELECTing from " \
"INFORMATION_SCHEMA.%s but " \
"the InnoDB storage engine " \
"is not installed", plugin_name); \
DBUG_RETURN(0); \
} \
} while (0)
#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && !defined __INTEL_COMPILER
#define STRUCT_FLD(name, value) name: value
#else
#define STRUCT_FLD(name, value) value
#endif
/* Don't use a static const variable here, as some C++ compilers (notably
HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
#define END_OF_ST_FIELD_INFO \
{STRUCT_FLD(field_name, NULL), \
STRUCT_FLD(field_length, 0), \
STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
STRUCT_FLD(value, 0), \
STRUCT_FLD(field_flags, 0), \
STRUCT_FLD(old_name, ""), \
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
/*
Use the following types mapping:
C type ST_FIELD_INFO::field_type
---------------------------------
long MYSQL_TYPE_LONGLONG
(field_length=MY_INT64_NUM_DECIMAL_DIGITS)
long unsigned MYSQL_TYPE_LONGLONG
(field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
char* MYSQL_TYPE_STRING
(field_length=n)
float MYSQL_TYPE_FLOAT
(field_length=0 is ignored)
void* MYSQL_TYPE_LONGLONG
(field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
boolean (if else) MYSQL_TYPE_LONG
(field_length=1)
time_t MYSQL_TYPE_DATETIME
(field_length=0 ignored)
---------------------------------
*/
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
INFORMATION_SCHEMA.innodb_locks
INFORMATION_SCHEMA.innodb_lock_waits
@return 0 on success */
static
int
trx_i_s_common_fill_table(
/*======================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
COND* cond); /*!< in: condition (not used) */
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
static
int
i_s_common_deinit(
/*==============*/
void* p); /*!< in/out: table schema object */
/*******************************************************************//**
Auxiliary function to store time_t value in MYSQL_TYPE_DATETIME
field.
@return 0 on success */
static
int
field_store_time_t(
/*===============*/
Field* field, /*!< in/out: target field for storage */
time_t time) /*!< in: value to store */
{
MYSQL_TIME my_time;
struct tm tm_time;
#if 0
/* use this if you are sure that `variables' and `time_zone'
are always initialized */
thd->variables.time_zone->gmt_sec_to_TIME(
&my_time, (my_time_t) time);
#else
localtime_r(&time, &tm_time);
localtime_to_TIME(&my_time, &tm_time);
my_time.time_type = MYSQL_TIMESTAMP_DATETIME;
#endif
return(field->store_time(&my_time, MYSQL_TIMESTAMP_DATETIME));
}
/*******************************************************************//**
Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
@return 0 on success */
static
int
field_store_string(
/*===============*/
Field* field, /*!< in/out: target field for storage */
const char* str) /*!< in: NUL-terminated utf-8 string,
or NULL */
{
int ret;
if (str != NULL) {
ret = field->store(str, strlen(str),
system_charset_info);
field->set_notnull();
} else {
ret = 0; /* success */
field->set_null();
}
return(ret);
}
/*******************************************************************//**
Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
If the value is ULINT_UNDEFINED then the field it set to NULL.
@return 0 on success */
static
int
field_store_ulint(
/*==============*/
Field* field, /*!< in/out: target field for storage */
ulint n) /*!< in: value to store */
{
int ret;
if (n != ULINT_UNDEFINED) {
ret = field->store(n);
field->set_notnull();
} else {
ret = 0; /* success */
field->set_null();
}
return(ret);
}
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
static ST_FIELD_INFO innodb_trx_fields_info[] =
{
#define IDX_TRX_ID 0
{STRUCT_FLD(field_name, "trx_id"),
STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_STATE 1
{STRUCT_FLD(field_name, "trx_state"),
STRUCT_FLD(field_length, TRX_QUE_STATE_STR_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_STARTED 2
{STRUCT_FLD(field_name, "trx_started"),
STRUCT_FLD(field_length, 0),
STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_REQUESTED_LOCK_ID 3
{STRUCT_FLD(field_name, "trx_requested_lock_id"),
STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_WAIT_STARTED 4
{STRUCT_FLD(field_name, "trx_wait_started"),
STRUCT_FLD(field_length, 0),
STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_WEIGHT 5
{STRUCT_FLD(field_name, "trx_weight"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_MYSQL_THREAD_ID 6
{STRUCT_FLD(field_name, "trx_mysql_thread_id"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_QUERY 7
{STRUCT_FLD(field_name, "trx_query"),
STRUCT_FLD(field_length, TRX_I_S_TRX_QUERY_MAX_LEN),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_OPERATION_STATE 8
{STRUCT_FLD(field_name, "trx_operation_state"),
STRUCT_FLD(field_length, TRX_I_S_TRX_OP_STATE_MAX_LEN),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_TABLES_IN_USE 9
{STRUCT_FLD(field_name, "trx_tables_in_use"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_TABLES_LOCKED 10
{STRUCT_FLD(field_name, "trx_tables_locked"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_LOCK_STRUCTS 11
{STRUCT_FLD(field_name, "trx_lock_structs"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_LOCK_MEMORY_BYTES 12
{STRUCT_FLD(field_name, "trx_lock_memory_bytes"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_ROWS_LOCKED 13
{STRUCT_FLD(field_name, "trx_rows_locked"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_ROWS_MODIFIED 14
{STRUCT_FLD(field_name, "trx_rows_modified"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_CONNCURRENCY_TICKETS 15
{STRUCT_FLD(field_name, "trx_concurrency_tickets"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_ISOLATION_LEVEL 16
{STRUCT_FLD(field_name, "trx_isolation_level"),
STRUCT_FLD(field_length, TRX_I_S_TRX_ISOLATION_LEVEL_MAX_LEN),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_UNIQUE_CHECKS 17
{STRUCT_FLD(field_name, "trx_unique_checks"),
STRUCT_FLD(field_length, 1),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 1),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_FOREIGN_KEY_CHECKS 18
{STRUCT_FLD(field_name, "trx_foreign_key_checks"),
STRUCT_FLD(field_length, 1),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 1),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_LAST_FOREIGN_KEY_ERROR 19
{STRUCT_FLD(field_name, "trx_last_foreign_key_error"),
STRUCT_FLD(field_length, TRX_I_S_TRX_FK_ERROR_MAX_LEN),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_ADAPTIVE_HASH_LATCHED 20
{STRUCT_FLD(field_name, "trx_adaptive_hash_latched"),
STRUCT_FLD(field_length, 1),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_TRX_ADAPTIVE_HASH_TIMEOUT 21
{STRUCT_FLD(field_name, "trx_adaptive_hash_timeout"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
/*******************************************************************//**
Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_trx
table with it.
@return 0 on success */
static
int
fill_innodb_trx_from_cache(
/*=======================*/
trx_i_s_cache_t* cache, /*!< in: cache to read from */
THD* thd, /*!< in: used to call
schema_table_store_record() */
TABLE* table) /*!< in/out: fill this table */
{
Field** fields;
ulint rows_num;
char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
ulint i;
DBUG_ENTER("fill_innodb_trx_from_cache");
fields = table->field;
rows_num = trx_i_s_cache_get_rows_used(cache,
I_S_INNODB_TRX);
for (i = 0; i < rows_num; i++) {
i_s_trx_row_t* row;
char trx_id[TRX_ID_MAX_LEN + 1];
row = (i_s_trx_row_t*)
trx_i_s_cache_get_nth_row(
cache, I_S_INNODB_TRX, i);
/* trx_id */
ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id);
OK(field_store_string(fields[IDX_TRX_ID], trx_id));
/* trx_state */
OK(field_store_string(fields[IDX_TRX_STATE],
row->trx_state));
/* trx_started */
OK(field_store_time_t(fields[IDX_TRX_STARTED],
(time_t) row->trx_started));
/* trx_requested_lock_id */
/* trx_wait_started */
if (row->trx_wait_started != 0) {
OK(field_store_string(
fields[IDX_TRX_REQUESTED_LOCK_ID],
trx_i_s_create_lock_id(
row->requested_lock_row,
lock_id, sizeof(lock_id))));
/* field_store_string() sets it no notnull */
OK(field_store_time_t(
fields[IDX_TRX_WAIT_STARTED],
(time_t) row->trx_wait_started));
fields[IDX_TRX_WAIT_STARTED]->set_notnull();
} else {
fields[IDX_TRX_REQUESTED_LOCK_ID]->set_null();
fields[IDX_TRX_WAIT_STARTED]->set_null();
}
/* trx_weight */
OK(fields[IDX_TRX_WEIGHT]->store((longlong) row->trx_weight,
true));
/* trx_mysql_thread_id */
OK(fields[IDX_TRX_MYSQL_THREAD_ID]->store(
row->trx_mysql_thread_id));
/* trx_query */
if (row->trx_query) {
/* store will do appropriate character set
conversion check */
fields[IDX_TRX_QUERY]->store(
row->trx_query, strlen(row->trx_query),
row->trx_query_cs);
fields[IDX_TRX_QUERY]->set_notnull();
} else {
fields[IDX_TRX_QUERY]->set_null();
}
/* trx_operation_state */
OK(field_store_string(fields[IDX_TRX_OPERATION_STATE],
row->trx_operation_state));
/* trx_tables_in_use */
OK(fields[IDX_TRX_TABLES_IN_USE]->store(
(longlong) row->trx_tables_in_use, true));
/* trx_tables_locked */
OK(fields[IDX_TRX_TABLES_LOCKED]->store(
(longlong) row->trx_tables_locked, true));
/* trx_lock_structs */
OK(fields[IDX_TRX_LOCK_STRUCTS]->store(
(longlong) row->trx_lock_structs, true));
/* trx_lock_memory_bytes */
OK(fields[IDX_TRX_LOCK_MEMORY_BYTES]->store(
(longlong) row->trx_lock_memory_bytes, true));
/* trx_rows_locked */
OK(fields[IDX_TRX_ROWS_LOCKED]->store(
(longlong) row->trx_rows_locked, true));
/* trx_rows_modified */
OK(fields[IDX_TRX_ROWS_MODIFIED]->store(
(longlong) row->trx_rows_modified, true));
/* trx_concurrency_tickets */
OK(fields[IDX_TRX_CONNCURRENCY_TICKETS]->store(
(longlong) row->trx_concurrency_tickets, true));
/* trx_isolation_level */
OK(field_store_string(fields[IDX_TRX_ISOLATION_LEVEL],
row->trx_isolation_level));
/* trx_unique_checks */
OK(fields[IDX_TRX_UNIQUE_CHECKS]->store(
row->trx_unique_checks));
/* trx_foreign_key_checks */
OK(fields[IDX_TRX_FOREIGN_KEY_CHECKS]->store(
row->trx_foreign_key_checks));
/* trx_last_foreign_key_error */
OK(field_store_string(fields[IDX_TRX_LAST_FOREIGN_KEY_ERROR],
row->trx_foreign_key_error));
/* trx_adaptive_hash_latched */
OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store(
row->trx_has_search_latch));
/* trx_adaptive_hash_timeout */
OK(fields[IDX_TRX_ADAPTIVE_HASH_TIMEOUT]->store(
(longlong) row->trx_search_latch_timeout, true));
OK(schema_table_store_record(thd, table));
}
DBUG_RETURN(0);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.innodb_trx
@return 0 on success */
static
int
innodb_trx_init(
/*============*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_trx_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = innodb_trx_fields_info;
schema->fill_table = trx_i_s_common_fill_table;
DBUG_RETURN(0);
}
static struct st_mysql_information_schema i_s_info =
{
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
};
UNIV_INTERN struct st_mysql_plugin i_s_innodb_trx =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_TRX"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB transactions"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, innodb_trx_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
#define IDX_LOCK_ID 0
{STRUCT_FLD(field_name, "lock_id"),
STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_TRX_ID 1
{STRUCT_FLD(field_name, "lock_trx_id"),
STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_MODE 2
{STRUCT_FLD(field_name, "lock_mode"),
/* S[,GAP] X[,GAP] IS[,GAP] IX[,GAP] AUTO_INC UNKNOWN */
STRUCT_FLD(field_length, 32),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_TYPE 3
{STRUCT_FLD(field_name, "lock_type"),
STRUCT_FLD(field_length, 32 /* RECORD|TABLE|UNKNOWN */),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_TABLE 4
{STRUCT_FLD(field_name, "lock_table"),
STRUCT_FLD(field_length, 1024),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_INDEX 5
{STRUCT_FLD(field_name, "lock_index"),
STRUCT_FLD(field_length, 1024),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_SPACE 6
{STRUCT_FLD(field_name, "lock_space"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_PAGE 7
{STRUCT_FLD(field_name, "lock_page"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_REC 8
{STRUCT_FLD(field_name, "lock_rec"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_LOCK_DATA 9
{STRUCT_FLD(field_name, "lock_data"),
STRUCT_FLD(field_length, TRX_I_S_LOCK_DATA_MAX_LEN),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
/*******************************************************************//**
Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_locks
table with it.
@return 0 on success */
static
int
fill_innodb_locks_from_cache(
/*=========================*/
trx_i_s_cache_t* cache, /*!< in: cache to read from */
THD* thd, /*!< in: MySQL client connection */
TABLE* table) /*!< in/out: fill this table */
{
Field** fields;
ulint rows_num;
char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
ulint i;
DBUG_ENTER("fill_innodb_locks_from_cache");
fields = table->field;
rows_num = trx_i_s_cache_get_rows_used(cache,
I_S_INNODB_LOCKS);
for (i = 0; i < rows_num; i++) {
i_s_locks_row_t* row;
char buf[MAX_FULL_NAME_LEN + 1];
const char* bufend;
char lock_trx_id[TRX_ID_MAX_LEN + 1];
row = (i_s_locks_row_t*)
trx_i_s_cache_get_nth_row(
cache, I_S_INNODB_LOCKS, i);
/* lock_id */
trx_i_s_create_lock_id(row, lock_id, sizeof(lock_id));
OK(field_store_string(fields[IDX_LOCK_ID],
lock_id));
/* lock_trx_id */
ut_snprintf(lock_trx_id, sizeof(lock_trx_id),
TRX_ID_FMT, row->lock_trx_id);
OK(field_store_string(fields[IDX_LOCK_TRX_ID], lock_trx_id));
/* lock_mode */
OK(field_store_string(fields[IDX_LOCK_MODE],
row->lock_mode));
/* lock_type */
OK(field_store_string(fields[IDX_LOCK_TYPE],
row->lock_type));
/* lock_table */
bufend = innobase_convert_name(buf, sizeof(buf),
row->lock_table,
strlen(row->lock_table),
thd, TRUE);
OK(fields[IDX_LOCK_TABLE]->store(buf, bufend - buf,
system_charset_info));
/* lock_index */
if (row->lock_index != NULL) {
bufend = innobase_convert_name(buf, sizeof(buf),
row->lock_index,
strlen(row->lock_index),
thd, FALSE);
OK(fields[IDX_LOCK_INDEX]->store(buf, bufend - buf,
system_charset_info));
fields[IDX_LOCK_INDEX]->set_notnull();
} else {
fields[IDX_LOCK_INDEX]->set_null();
}
/* lock_space */
OK(field_store_ulint(fields[IDX_LOCK_SPACE],
row->lock_space));
/* lock_page */
OK(field_store_ulint(fields[IDX_LOCK_PAGE],
row->lock_page));
/* lock_rec */
OK(field_store_ulint(fields[IDX_LOCK_REC],
row->lock_rec));
/* lock_data */
OK(field_store_string(fields[IDX_LOCK_DATA],
row->lock_data));
OK(schema_table_store_record(thd, table));
}
DBUG_RETURN(0);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.innodb_locks
@return 0 on success */
static
int
innodb_locks_init(
/*==============*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_locks_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = innodb_locks_fields_info;
schema->fill_table = trx_i_s_common_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_locks =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_LOCKS"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB conflicting locks"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, innodb_locks_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
#define IDX_REQUESTING_TRX_ID 0
{STRUCT_FLD(field_name, "requesting_trx_id"),
STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_REQUESTED_LOCK_ID 1
{STRUCT_FLD(field_name, "requested_lock_id"),
STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BLOCKING_TRX_ID 2
{STRUCT_FLD(field_name, "blocking_trx_id"),
STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BLOCKING_LOCK_ID 3
{STRUCT_FLD(field_name, "blocking_lock_id"),
STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
/*******************************************************************//**
Read data from cache buffer and fill the
INFORMATION_SCHEMA.innodb_lock_waits table with it.
@return 0 on success */
static
int
fill_innodb_lock_waits_from_cache(
/*==============================*/
trx_i_s_cache_t* cache, /*!< in: cache to read from */
THD* thd, /*!< in: used to call
schema_table_store_record() */
TABLE* table) /*!< in/out: fill this table */
{
Field** fields;
ulint rows_num;
char requested_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
char blocking_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
ulint i;
DBUG_ENTER("fill_innodb_lock_waits_from_cache");
fields = table->field;
rows_num = trx_i_s_cache_get_rows_used(cache,
I_S_INNODB_LOCK_WAITS);
for (i = 0; i < rows_num; i++) {
i_s_lock_waits_row_t* row;
char requesting_trx_id[TRX_ID_MAX_LEN + 1];
char blocking_trx_id[TRX_ID_MAX_LEN + 1];
row = (i_s_lock_waits_row_t*)
trx_i_s_cache_get_nth_row(
cache, I_S_INNODB_LOCK_WAITS, i);
/* requesting_trx_id */
ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id),
TRX_ID_FMT, row->requested_lock_row->lock_trx_id);
OK(field_store_string(fields[IDX_REQUESTING_TRX_ID],
requesting_trx_id));
/* requested_lock_id */
OK(field_store_string(
fields[IDX_REQUESTED_LOCK_ID],
trx_i_s_create_lock_id(
row->requested_lock_row,
requested_lock_id,
sizeof(requested_lock_id))));
/* blocking_trx_id */
ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id),
TRX_ID_FMT, row->blocking_lock_row->lock_trx_id);
OK(field_store_string(fields[IDX_BLOCKING_TRX_ID],
blocking_trx_id));
/* blocking_lock_id */
OK(field_store_string(
fields[IDX_BLOCKING_LOCK_ID],
trx_i_s_create_lock_id(
row->blocking_lock_row,
blocking_lock_id,
sizeof(blocking_lock_id))));
OK(schema_table_store_record(thd, table));
}
DBUG_RETURN(0);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.innodb_lock_waits
@return 0 on success */
static
int
innodb_lock_waits_init(
/*===================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_lock_waits_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = innodb_lock_waits_fields_info;
schema->fill_table = trx_i_s_common_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, innodb_lock_waits_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
INFORMATION_SCHEMA.innodb_locks
INFORMATION_SCHEMA.innodb_lock_waits
@return 0 on success */
static
int
trx_i_s_common_fill_table(
/*======================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
COND* cond) /*!< in: condition (not used) */
{
const char* table_name;
int ret;
trx_i_s_cache_t* cache;
DBUG_ENTER("trx_i_s_common_fill_table");
/* deny access to non-superusers */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
/* minimize the number of places where global variables are
referenced */
cache = trx_i_s_cache;
/* which table we have to fill? */
table_name = tables->schema_table_name;
/* or table_name = tables->schema_table->table_name; */
RETURN_IF_INNODB_NOT_STARTED(table_name);
/* update the cache */
trx_i_s_cache_start_write(cache);
trx_i_s_possibly_fetch_data_into_cache(cache);
trx_i_s_cache_end_write(cache);
if (trx_i_s_cache_is_truncated(cache)) {
/* XXX show warning to user if possible */
fprintf(stderr, "Warning: data in %s truncated due to "
"memory limit of %d bytes\n", table_name,
TRX_I_S_MEM_LIMIT);
}
ret = 0;
trx_i_s_cache_start_read(cache);
if (innobase_strcasecmp(table_name, "innodb_trx") == 0) {
if (fill_innodb_trx_from_cache(
cache, thd, tables->table) != 0) {
ret = 1;
}
} else if (innobase_strcasecmp(table_name, "innodb_locks") == 0) {
if (fill_innodb_locks_from_cache(
cache, thd, tables->table) != 0) {
ret = 1;
}
} else if (innobase_strcasecmp(table_name, "innodb_lock_waits") == 0) {
if (fill_innodb_lock_waits_from_cache(
cache, thd, tables->table) != 0) {
ret = 1;
}
} else {
/* huh! what happened!? */
fprintf(stderr,
"InnoDB: trx_i_s_common_fill_table() was "
"called to fill unknown table: %s.\n"
"This function only knows how to fill "
"innodb_trx, innodb_locks and "
"innodb_lock_waits tables.\n", table_name);
ret = 1;
}
trx_i_s_cache_end_read(cache);
#if 0
DBUG_RETURN(ret);
#else
/* if this function returns something else than 0 then a
deadlock occurs between the mysqld server and mysql client,
see http://bugs.mysql.com/29900 ; when that bug is resolved
we can enable the DBUG_RETURN(ret) above */
ret++; // silence a gcc46 warning
DBUG_RETURN(0);
#endif
}
/* Fields of the dynamic table information_schema.innodb_cmp. */
static ST_FIELD_INFO i_s_cmp_fields_info[] =
{
{STRUCT_FLD(field_name, "page_size"),
STRUCT_FLD(field_length, 5),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Compressed Page Size"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "compress_ops"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Total Number of Compressions"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "compress_ops_ok"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Total Number of"
" Successful Compressions"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "compress_time"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Total Duration of Compressions,"
" in Seconds"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "uncompress_ops"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Total Number of Decompressions"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "uncompress_time"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Total Duration of Decompressions,"
" in Seconds"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
/*******************************************************************//**
Fill the dynamic table information_schema.innodb_cmp or
innodb_cmp_reset.
@return 0 on success, 1 on failure */
static
int
i_s_cmp_fill_low(
/*=============*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
COND* cond, /*!< in: condition (ignored) */
ibool reset) /*!< in: TRUE=reset cumulated counts */
{
TABLE* table = (TABLE *) tables->table;
int status = 0;
DBUG_ENTER("i_s_cmp_fill_low");
/* deny access to non-superusers */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
for (uint i = 0; i < PAGE_ZIP_NUM_SSIZE - 1; i++) {
page_zip_stat_t* zip_stat = &page_zip_stat[i];
table->field[0]->store(PAGE_ZIP_MIN_SIZE << i);
/* The cumulated counts are not protected by any
mutex. Thus, some operation in page0zip.c could
increment a counter between the time we read it and
clear it. We could introduce mutex protection, but it
could cause a measureable performance hit in
page0zip.c. */
table->field[1]->store(zip_stat->compressed);
table->field[2]->store(zip_stat->compressed_ok);
table->field[3]->store(
(ulong) (zip_stat->compressed_usec / 1000000));
table->field[4]->store(zip_stat->decompressed);
table->field[5]->store(
(ulong) (zip_stat->decompressed_usec / 1000000));
if (reset) {
memset(zip_stat, 0, sizeof *zip_stat);
}
if (schema_table_store_record(thd, table)) {
status = 1;
break;
}
}
DBUG_RETURN(status);
}
/*******************************************************************//**
Fill the dynamic table information_schema.innodb_cmp.
@return 0 on success, 1 on failure */
static
int
i_s_cmp_fill(
/*=========*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
COND* cond) /*!< in: condition (ignored) */
{
return(i_s_cmp_fill_low(thd, tables, cond, FALSE));
}
/*******************************************************************//**
Fill the dynamic table information_schema.innodb_cmp_reset.
@return 0 on success, 1 on failure */
static
int
i_s_cmp_reset_fill(
/*===============*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
COND* cond) /*!< in: condition (ignored) */
{
return(i_s_cmp_fill_low(thd, tables, cond, TRUE));
}
/*******************************************************************//**
Bind the dynamic table information_schema.innodb_cmp.
@return 0 on success */
static
int
i_s_cmp_init(
/*=========*/
void* p) /*!< in/out: table schema object */
{
DBUG_ENTER("i_s_cmp_init");
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = i_s_cmp_fields_info;
schema->fill_table = i_s_cmp_fill;
DBUG_RETURN(0);
}
/*******************************************************************//**
Bind the dynamic table information_schema.innodb_cmp_reset.
@return 0 on success */
static
int
i_s_cmp_reset_init(
/*===============*/
void* p) /*!< in/out: table schema object */
{
DBUG_ENTER("i_s_cmp_reset_init");
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = i_s_cmp_fields_info;
schema->fill_table = i_s_cmp_reset_fill;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_CMP"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, i_s_cmp_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_CMP_RESET"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
" reset cumulated counts"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, i_s_cmp_reset_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
{STRUCT_FLD(field_name, "page_size"),
STRUCT_FLD(field_length, 5),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Buddy Block Size"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "buffer_pool_instance"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Buffer Pool Id"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "pages_used"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Currently in Use"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "pages_free"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Currently Available"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "relocation_ops"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Total Number of Relocations"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "relocation_time"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, "Total Duration of Relocations,"
" in Seconds"),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
/*******************************************************************//**
Fill the dynamic table information_schema.innodb_cmpmem or
innodb_cmpmem_reset.
@return 0 on success, 1 on failure */
static
int
i_s_cmpmem_fill_low(
/*================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
COND* cond, /*!< in: condition (ignored) */
ibool reset) /*!< in: TRUE=reset cumulated counts */
{
int status = 0;
TABLE* table = (TABLE *) tables->table;
DBUG_ENTER("i_s_cmpmem_fill_low");
/* deny access to non-superusers */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
status = 0;
buf_pool = buf_pool_from_array(i);
buf_pool_mutex_enter(buf_pool);
for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
buf_buddy_stat_t* buddy_stat;
buddy_stat = &buf_pool->buddy_stat[x];
table->field[0]->store(BUF_BUDDY_LOW << x);
table->field[1]->store(i);
table->field[2]->store(buddy_stat->used);
table->field[3]->store(UNIV_LIKELY(x < BUF_BUDDY_SIZES)
? UT_LIST_GET_LEN(buf_pool->zip_free[x])
: 0);
table->field[4]->store((longlong)
buddy_stat->relocated, true);
table->field[5]->store(
(ulong) (buddy_stat->relocated_usec / 1000000));
if (reset) {
/* This is protected by buf_pool->mutex. */
buddy_stat->relocated = 0;
buddy_stat->relocated_usec = 0;
}
if (schema_table_store_record(thd, table)) {
status = 1;
break;
}
}
buf_pool_mutex_exit(buf_pool);
if (status) {
break;
}
}
DBUG_RETURN(status);
}
/*******************************************************************//**
Fill the dynamic table information_schema.innodb_cmpmem.
@return 0 on success, 1 on failure */
static
int
i_s_cmpmem_fill(
/*============*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
COND* cond) /*!< in: condition (ignored) */
{
return(i_s_cmpmem_fill_low(thd, tables, cond, FALSE));
}
/*******************************************************************//**
Fill the dynamic table information_schema.innodb_cmpmem_reset.
@return 0 on success, 1 on failure */
static
int
i_s_cmpmem_reset_fill(
/*==================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
COND* cond) /*!< in: condition (ignored) */
{
return(i_s_cmpmem_fill_low(thd, tables, cond, TRUE));
}
/*******************************************************************//**
Bind the dynamic table information_schema.innodb_cmpmem.
@return 0 on success */
static
int
i_s_cmpmem_init(
/*============*/
void* p) /*!< in/out: table schema object */
{
DBUG_ENTER("i_s_cmpmem_init");
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = i_s_cmpmem_fields_info;
schema->fill_table = i_s_cmpmem_fill;
DBUG_RETURN(0);
}
/*******************************************************************//**
Bind the dynamic table information_schema.innodb_cmpmem_reset.
@return 0 on success */
static
int
i_s_cmpmem_reset_init(
/*==================*/
void* p) /*!< in/out: table schema object */
{
DBUG_ENTER("i_s_cmpmem_reset_init");
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = i_s_cmpmem_fields_info;
schema->fill_table = i_s_cmpmem_reset_fill;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_CMPMEM"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, i_s_cmpmem_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
" reset cumulated counts"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, i_s_cmpmem_reset_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
/* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */
static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] =
{
#define IDX_BUF_STATS_POOL_ID 0
{STRUCT_FLD(field_name, "POOL_ID"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_POOL_SIZE 1
{STRUCT_FLD(field_name, "POOL_SIZE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_FREE_BUFFERS 2
{STRUCT_FLD(field_name, "FREE_BUFFERS"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_LRU_LEN 3
{STRUCT_FLD(field_name, "DATABASE_PAGES"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_OLD_LRU_LEN 4
{STRUCT_FLD(field_name, "OLD_DATABASE_PAGES"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_FLUSH_LIST_LEN 5
{STRUCT_FLD(field_name, "MODIFIED_DATABASE_PAGES"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PENDING_ZIP 6
{STRUCT_FLD(field_name, "PENDING_DECOMPRESS"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PENDING_READ 7
{STRUCT_FLD(field_name, "PENDING_READS"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_FLUSH_LRU 8
{STRUCT_FLD(field_name, "PENDING_FLUSH_LRU"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_FLUSH_LIST 9
{STRUCT_FLD(field_name, "PENDING_FLUSH_LIST"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_YOUNG 10
{STRUCT_FLD(field_name, "PAGES_MADE_YOUNG"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_NOT_YOUNG 11
{STRUCT_FLD(field_name, "PAGES_NOT_MADE_YOUNG"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_YOUNG_RATE 12
{STRUCT_FLD(field_name, "PAGES_MADE_YOUNG_RATE"),
STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13
{STRUCT_FLD(field_name, "PAGES_MADE_NOT_YOUNG_RATE"),
STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_READ 14
{STRUCT_FLD(field_name, "NUMBER_PAGES_READ"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_CREATED 15
{STRUCT_FLD(field_name, "NUMBER_PAGES_CREATED"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_WRITTEN 16
{STRUCT_FLD(field_name, "NUMBER_PAGES_WRITTEN"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_READ_RATE 17
{STRUCT_FLD(field_name, "PAGES_READ_RATE"),
STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_CREATE_RATE 18
{STRUCT_FLD(field_name, "PAGES_CREATE_RATE"),
STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_PAGE_WRITTEN_RATE 19
{STRUCT_FLD(field_name, "PAGES_WRITTEN_RATE"),
STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_GET 20
{STRUCT_FLD(field_name, "NUMBER_PAGES_GET"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_HIT_RATE 21
{STRUCT_FLD(field_name, "HIT_RATE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_MADE_YOUNG_PCT 22
{STRUCT_FLD(field_name, "YOUNG_MAKE_PER_THOUSAND_GETS"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23
{STRUCT_FLD(field_name, "NOT_YOUNG_MAKE_PER_THOUSAND_GETS"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_READ_AHREAD 24
{STRUCT_FLD(field_name, "NUMBER_PAGES_READ_AHEAD"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_READ_AHEAD_EVICTED 25
{STRUCT_FLD(field_name, "NUMBER_READ_AHEAD_EVICTED"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_READ_AHEAD_RATE 26
{STRUCT_FLD(field_name, "READ_AHEAD_RATE"),
STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27
{STRUCT_FLD(field_name, "READ_AHEAD_EVICTED_RATE"),
STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_LRU_IO_SUM 28
{STRUCT_FLD(field_name, "LRU_IO_TOTAL"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_LRU_IO_CUR 29
{STRUCT_FLD(field_name, "LRU_IO_CURRENT"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_UNZIP_SUM 30
{STRUCT_FLD(field_name, "UNCOMPRESS_TOTAL"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_STATS_UNZIP_CUR 31
{STRUCT_FLD(field_name, "UNCOMPRESS_CURRENT"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
/*******************************************************************//**
Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular
buffer pool
@return 0 on success, 1 on failure */
static
int
i_s_innodb_stats_fill(
/*==================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
const buf_pool_info_t* info) /*!< in: buffer pool
information */
{
TABLE* table;
Field** fields;
DBUG_ENTER("i_s_innodb_stats_fill");
table = tables->table;
fields = table->field;
OK(fields[IDX_BUF_STATS_POOL_ID]->store(info->pool_unique_id));
OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(info->pool_size));
OK(fields[IDX_BUF_STATS_LRU_LEN]->store(info->lru_len));
OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(info->old_lru_len));
OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(info->free_list_len));
OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store(
info->flush_list_len));
OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(info->n_pend_unzip));
OK(fields[IDX_BUF_STATS_PENDING_READ]->store(info->n_pend_reads));
OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(info->n_pending_flush_lru));
OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(info->n_pending_flush_list));
OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(info->n_pages_made_young));
OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store(
info->n_pages_not_made_young));
OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store(
info->page_made_young_rate));
OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store(
info->page_not_made_young_rate));
OK(fields[IDX_BUF_STATS_PAGE_READ]->store(info->n_pages_read));
OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(info->n_pages_created));
OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(info->n_pages_written));
OK(fields[IDX_BUF_STATS_GET]->store(info->n_page_gets));
OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(info->pages_read_rate));
OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(info->pages_created_rate));
OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(info->pages_written_rate));
if (info->n_page_get_delta) {
OK(fields[IDX_BUF_STATS_HIT_RATE]->store(
1000 - (1000 * info->page_read_delta
/ info->n_page_get_delta)));
OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(
1000 * info->young_making_delta
/ info->n_page_get_delta));
OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(
1000 * info->not_young_making_delta
/ info->n_page_get_delta));
} else {
OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0));
OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0));
OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0));
}
OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(info->n_ra_pages_read));
OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store(
info->n_ra_pages_evicted));
OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store(
info->pages_readahead_rate));
OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store(
info->pages_evicted_rate));
OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(info->io_sum));
OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(info->io_cur));
OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(info->unzip_sum));
OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store( info->unzip_cur));
DBUG_RETURN(schema_table_store_record(thd, table));
}
/*******************************************************************//**
This is the function that loops through each buffer pool and fetch buffer
pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS
@return 0 on success, 1 on failure */
static
int
i_s_innodb_buffer_stats_fill_table(
/*===============================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (ignored) */
{
int status = 0;
buf_pool_info_t* pool_info;
DBUG_ENTER("i_s_innodb_buffer_fill_general");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* Only allow the PROCESS privilege holder to access the stats */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
pool_info = (buf_pool_info_t*) mem_zalloc(
srv_buf_pool_instances * sizeof *pool_info);
/* Walk through each buffer pool */
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
/* Fetch individual buffer pool info */
buf_stats_get_pool_info(buf_pool, i, pool_info);
status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]);
/* If something goes wrong, break and return */
if (status) {
break;
}
}
mem_free(pool_info);
DBUG_RETURN(status);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS.
@return 0 on success, 1 on failure */
static
int
i_s_innodb_buffer_pool_stats_init(
/*==============================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("i_s_innodb_buffer_pool_stats_init");
schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
schema->fields_info = i_s_innodb_buffer_stats_fields_info;
schema->fill_table = i_s_innodb_buffer_stats_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_stats =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
/* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] =
{
#define IDX_BUFFER_POOL_ID 0
{STRUCT_FLD(field_name, "POOL_ID"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_BLOCK_ID 1
{STRUCT_FLD(field_name, "BLOCK_ID"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_SPACE 2
{STRUCT_FLD(field_name, "SPACE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_NUM 3
{STRUCT_FLD(field_name, "PAGE_NUMBER"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_TYPE 4
{STRUCT_FLD(field_name, "PAGE_TYPE"),
STRUCT_FLD(field_length, 64),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_FLUSH_TYPE 5
{STRUCT_FLD(field_name, "FLUSH_TYPE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_FIX_COUNT 6
{STRUCT_FLD(field_name, "FIX_COUNT"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_HASHED 7
{STRUCT_FLD(field_name, "IS_HASHED"),
STRUCT_FLD(field_length, 3),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_NEWEST_MOD 8
{STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_OLDEST_MOD 9
{STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_ACCESS_TIME 10
{STRUCT_FLD(field_name, "ACCESS_TIME"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_TABLE_NAME 11
{STRUCT_FLD(field_name, "TABLE_NAME"),
STRUCT_FLD(field_length, 1024),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_INDEX_NAME 12
{STRUCT_FLD(field_name, "INDEX_NAME"),
STRUCT_FLD(field_length, 1024),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_NUM_RECS 13
{STRUCT_FLD(field_name, "NUMBER_RECORDS"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_DATA_SIZE 14
{STRUCT_FLD(field_name, "DATA_SIZE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_ZIP_SIZE 15
{STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_STATE 16
{STRUCT_FLD(field_name, "PAGE_STATE"),
STRUCT_FLD(field_length, 64),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_IO_FIX 17
{STRUCT_FLD(field_name, "IO_FIX"),
STRUCT_FLD(field_length, 64),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_IS_OLD 18
{STRUCT_FLD(field_name, "IS_OLD"),
STRUCT_FLD(field_length, 3),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUFFER_PAGE_FREE_CLOCK 19
{STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
/*******************************************************************//**
Fill Information Schema table INNODB_BUFFER_PAGE with information
cached in the buf_page_info_t array
@return 0 on success, 1 on failure */
static
int
i_s_innodb_buffer_page_fill(
/*========================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
const buf_page_info_t* info_array, /*!< in: array cached page
info */
ulint num_page, /*!< in: number of page info
cached */
mem_heap_t* heap) /*!< in: temp heap memory */
{
TABLE* table;
Field** fields;
DBUG_ENTER("i_s_innodb_buffer_page_fill");
table = tables->table;
fields = table->field;
/* Iterate through the cached array and fill the I_S table rows */
for (ulint i = 0; i < num_page; i++) {
const buf_page_info_t* page_info;
const char* table_name;
const char* index_name;
const char* state_str;
enum buf_page_state state;
page_info = info_array + i;
table_name = NULL;
index_name = NULL;
state_str = NULL;
OK(fields[IDX_BUFFER_POOL_ID]->store(page_info->pool_id));
OK(fields[IDX_BUFFER_BLOCK_ID]->store(page_info->block_id));
OK(fields[IDX_BUFFER_PAGE_SPACE]->store(page_info->space_id));
OK(fields[IDX_BUFFER_PAGE_NUM]->store(page_info->page_num));
OK(field_store_string(
fields[IDX_BUFFER_PAGE_TYPE],
i_s_page_type[page_info->page_type].type_str));
OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(
page_info->flush_type));
OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
page_info->fix_count));
if (page_info->hashed) {
OK(field_store_string(
fields[IDX_BUFFER_PAGE_HASHED], "YES"));
} else {
OK(field_store_string(
fields[IDX_BUFFER_PAGE_HASHED], "NO"));
}
OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store(
(longlong) page_info->newest_mod, true));
OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store(
(longlong) page_info->oldest_mod, true));
OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store(
page_info->access_time));
/* If this is an index page, fetch the index name
and table name */
if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
const dict_index_t* index;
mutex_enter(&dict_sys->mutex);
index = dict_index_get_if_in_cache_low(
page_info->index_id);
/* Copy the index/table name under mutex. We
do not want to hold the InnoDB mutex while
filling the IS table */
if (index) {
const char* name_ptr = index->name;
if (name_ptr[0] == TEMP_INDEX_PREFIX) {
name_ptr++;
}
index_name = mem_heap_strdup(heap, name_ptr);
table_name = mem_heap_strdup(heap,
index->table_name);
DBUG_EXECUTE_IF("mysql_test_print_index_type",
{
char idx_type[3];
ut_snprintf(idx_type,
sizeof(idx_type),
"%d",
index->type);
index_name=mem_heap_strcat(heap,
index_name,
idx_type);
};);
}
mutex_exit(&dict_sys->mutex);
}
OK(field_store_string(
fields[IDX_BUFFER_PAGE_TABLE_NAME], table_name));
OK(field_store_string(
fields[IDX_BUFFER_PAGE_INDEX_NAME], index_name));
OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
page_info->num_recs));
OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store(
page_info->data_size));
OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store(
page_info->zip_ssize
? (PAGE_ZIP_MIN_SIZE >> 1) << page_info->zip_ssize
: 0));
#if BUF_PAGE_STATE_BITS > 3
# error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for"
#endif
state = static_cast<enum buf_page_state>(page_info->page_state);
switch (state) {
/* First three states are for compression pages and
are not states we would get as we scan pages through
buffer blocks */
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
state_str = NULL;
break;
case BUF_BLOCK_NOT_USED:
state_str = "NOT_USED";
break;
case BUF_BLOCK_READY_FOR_USE:
state_str = "READY_FOR_USE";
break;
case BUF_BLOCK_FILE_PAGE:
state_str = "FILE_PAGE";
break;
case BUF_BLOCK_MEMORY:
state_str = "MEMORY";
break;
case BUF_BLOCK_REMOVE_HASH:
state_str = "REMOVE_HASH";
break;
};
OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE],
state_str));
switch (page_info->io_fix) {
case BUF_IO_NONE:
OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
"IO_NONE"));
break;
case BUF_IO_READ:
OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
"IO_READ"));
break;
case BUF_IO_WRITE:
OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
"IO_WRITE"));
break;
case BUF_IO_PIN:
OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
"IO_PIN"));
break;
}
OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD],
(page_info->is_old) ? "YES" : "NO"));
OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store(
page_info->freed_page_clock));
if (schema_table_store_record(thd, table)) {
DBUG_RETURN(1);
}
}
DBUG_RETURN(0);
}
/*******************************************************************//**
Set appropriate page type to a buf_page_info_t structure */
static
void
i_s_innodb_set_page_type(
/*=====================*/
buf_page_info_t*page_info, /*!< in/out: structure to fill with
scanned info */
ulint page_type, /*!< in: page type */
const byte* frame) /*!< in: buffer frame */
{
if (page_type == FIL_PAGE_INDEX) {
const page_t* page = (const page_t*) frame;
page_info->index_id = btr_page_get_index_id(page);
/* FIL_PAGE_INDEX is a bit special, its value
is defined as 17855, so we cannot use FIL_PAGE_INDEX
to index into i_s_page_type[] array, its array index
in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX
(1) for index pages or I_S_PAGE_TYPE_IBUF for
change buffer index pages */
if (page_info->index_id
== static_cast<index_id_t>(DICT_IBUF_ID_MIN
+ IBUF_SPACE_ID)) {
page_info->page_type = I_S_PAGE_TYPE_IBUF;
} else {
page_info->page_type = I_S_PAGE_TYPE_INDEX;
}
page_info->data_size = (ulint)(page_header_get_field(
page, PAGE_HEAP_TOP) - (page_is_comp(page)
? PAGE_NEW_SUPREMUM_END
: PAGE_OLD_SUPREMUM_END)
- page_header_get_field(page, PAGE_GARBAGE));
page_info->num_recs = page_get_n_recs(page);
} else if (page_type > FIL_PAGE_TYPE_LAST) {
/* Encountered an unknown page type */
page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
} else {
/* Make sure we get the right index into the
i_s_page_type[] array */
ut_a(page_type == i_s_page_type[page_type].type_value);
page_info->page_type = page_type;
}
if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB
|| page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) {
page_info->page_num = mach_read_from_4(
frame + FIL_PAGE_OFFSET);
page_info->space_id = mach_read_from_4(
frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
}
}
/*******************************************************************//**
Scans pages in the buffer cache, and collect their general information
into the buf_page_info_t array which is zero-filled. So any fields
that are not initialized in the function will default to 0 */
static
void
i_s_innodb_buffer_page_get_info(
/*============================*/
const buf_page_t*bpage, /*!< in: buffer pool page to scan */
ulint pool_id, /*!< in: buffer pool id */
ulint pos, /*!< in: buffer block position in
buffer pool or in the LRU list */
buf_page_info_t*page_info) /*!< in: zero filled info structure;
out: structure filled with scanned
info */
{
ut_ad(pool_id < MAX_BUFFER_POOLS);
page_info->pool_id = pool_id;
page_info->block_id = pos;
page_info->page_state = buf_page_get_state(bpage);
/* Only fetch information for buffers that map to a tablespace,
that is, buffer page with state BUF_BLOCK_ZIP_PAGE,
BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */
if (buf_page_in_file(bpage)) {
const byte* frame;
ulint page_type;
page_info->space_id = buf_page_get_space(bpage);
page_info->page_num = buf_page_get_page_no(bpage);
page_info->flush_type = bpage->flush_type;
page_info->fix_count = bpage->buf_fix_count;
page_info->newest_mod = bpage->newest_modification;
page_info->oldest_mod = bpage->oldest_modification;
page_info->access_time = bpage->access_time;
page_info->zip_ssize = bpage->zip.ssize;
page_info->io_fix = bpage->io_fix;
page_info->is_old = bpage->old;
page_info->freed_page_clock = bpage->freed_page_clock;
switch (buf_page_get_io_fix(bpage)) {
case BUF_IO_NONE:
case BUF_IO_WRITE:
case BUF_IO_PIN:
break;
case BUF_IO_READ:
page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
return;
}
if (page_info->page_state == BUF_BLOCK_FILE_PAGE) {
const buf_block_t*block;
block = reinterpret_cast<const buf_block_t*>(bpage);
frame = block->frame;
page_info->hashed = (block->index != NULL);
} else {
ut_ad(page_info->zip_ssize);
frame = bpage->zip.data;
}
page_type = fil_page_get_type(frame);
i_s_innodb_set_page_type(page_info, page_type, frame);
} else {
page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
}
}
/*******************************************************************//**
This is the function that goes through each block of the buffer pool
and fetch information to information schema tables: INNODB_BUFFER_PAGE.
@return 0 on success, 1 on failure */
static
int
i_s_innodb_fill_buffer_pool(
/*========================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
const ulint pool_id) /*!< in: buffer pool id */
{
int status = 0;
mem_heap_t* heap;
DBUG_ENTER("i_s_innodb_fill_buffer_pool");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
heap = mem_heap_create(10000);
/* Go through each chunk of buffer pool. Currently, we only
have one single chunk for each buffer pool */
for (ulint n = 0; n < buf_pool->n_chunks; n++) {
const buf_block_t* block;
ulint n_blocks;
buf_page_info_t* info_buffer;
ulint num_page;
ulint mem_size;
ulint chunk_size;
ulint num_to_process = 0;
ulint block_id = 0;
/* Get buffer block of the nth chunk */
block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size);
num_page = 0;
while (chunk_size > 0) {
/* we cache maximum MAX_BUF_INFO_CACHED number of
buffer page info */
num_to_process = ut_min(chunk_size,
MAX_BUF_INFO_CACHED);
mem_size = num_to_process * sizeof(buf_page_info_t);
/* For each chunk, we'll pre-allocate information
structures to cache the page information read from
the buffer pool. Doing so before obtain any mutex */
info_buffer = (buf_page_info_t*) mem_heap_zalloc(
heap, mem_size);
/* Obtain appropriate mutexes. Since this is diagnostic
buffer pool info printout, we are not required to
preserve the overall consistency, so we can
release mutex periodically */
buf_pool_mutex_enter(buf_pool);
/* GO through each block in the chunk */
for (n_blocks = num_to_process; n_blocks--; block++) {
i_s_innodb_buffer_page_get_info(
&block->page, pool_id, block_id,
info_buffer + num_page);
block_id++;
num_page++;
}
buf_pool_mutex_exit(buf_pool);
/* Fill in information schema table with information
just collected from the buffer chunk scan */
status = i_s_innodb_buffer_page_fill(
thd, tables, info_buffer,
num_page, heap);
/* If something goes wrong, break and return */
if (status) {
break;
}
mem_heap_empty(heap);
chunk_size -= num_to_process;
num_page = 0;
}
}
mem_heap_free(heap);
DBUG_RETURN(status);
}
/*******************************************************************//**
Fill page information for pages in InnoDB buffer pool to the
dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
@return 0 on success, 1 on failure */
static
int
i_s_innodb_buffer_page_fill_table(
/*==============================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (ignored) */
{
int status = 0;
DBUG_ENTER("i_s_innodb_buffer_page_fill_table");
/* deny access to user without PROCESS privilege */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
/* Walk through each buffer pool */
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
/* Fetch information from pages in this buffer pool,
and fill the corresponding I_S table */
status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i);
/* If something wrong, break and return */
if (status) {
break;
}
}
DBUG_RETURN(status);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.
@return 0 on success, 1 on failure */
static
int
i_s_innodb_buffer_page_init(
/*========================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("i_s_innodb_buffer_page_init");
schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
schema->fields_info = i_s_innodb_buffer_page_fields_info;
schema->fill_table = i_s_innodb_buffer_page_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_BUFFER_PAGE"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB Buffer Page Information"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, i_s_innodb_buffer_page_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] =
{
#define IDX_BUF_LRU_POOL_ID 0
{STRUCT_FLD(field_name, "POOL_ID"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_POS 1
{STRUCT_FLD(field_name, "LRU_POSITION"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_SPACE 2
{STRUCT_FLD(field_name, "SPACE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_NUM 3
{STRUCT_FLD(field_name, "PAGE_NUMBER"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_TYPE 4
{STRUCT_FLD(field_name, "PAGE_TYPE"),
STRUCT_FLD(field_length, 64),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5
{STRUCT_FLD(field_name, "FLUSH_TYPE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_FIX_COUNT 6
{STRUCT_FLD(field_name, "FIX_COUNT"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_HASHED 7
{STRUCT_FLD(field_name, "IS_HASHED"),
STRUCT_FLD(field_length, 3),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_NEWEST_MOD 8
{STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_OLDEST_MOD 9
{STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_ACCESS_TIME 10
{STRUCT_FLD(field_name, "ACCESS_TIME"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_TABLE_NAME 11
{STRUCT_FLD(field_name, "TABLE_NAME"),
STRUCT_FLD(field_length, 1024),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_INDEX_NAME 12
{STRUCT_FLD(field_name, "INDEX_NAME"),
STRUCT_FLD(field_length, 1024),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_NUM_RECS 13
{STRUCT_FLD(field_name, "NUMBER_RECORDS"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_DATA_SIZE 14
{STRUCT_FLD(field_name, "DATA_SIZE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_ZIP_SIZE 15
{STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_STATE 16
{STRUCT_FLD(field_name, "COMPRESSED"),
STRUCT_FLD(field_length, 3),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_IO_FIX 17
{STRUCT_FLD(field_name, "IO_FIX"),
STRUCT_FLD(field_length, 64),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_IS_OLD 18
{STRUCT_FLD(field_name, "IS_OLD"),
STRUCT_FLD(field_length, 3),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define IDX_BUF_LRU_PAGE_FREE_CLOCK 19
{STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
END_OF_ST_FIELD_INFO
};
/*******************************************************************//**
Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information
cached in the buf_page_info_t array
@return 0 on success, 1 on failure */
static
int
i_s_innodb_buf_page_lru_fill(
/*=========================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
const buf_page_info_t* info_array, /*!< in: array cached page
info */
ulint num_page) /*!< in: number of page info
cached */
{
TABLE* table;
Field** fields;
mem_heap_t* heap;
DBUG_ENTER("i_s_innodb_buf_page_lru_fill");
table = tables->table;
fields = table->field;
heap = mem_heap_create(1000);
/* Iterate through the cached array and fill the I_S table rows */
for (ulint i = 0; i < num_page; i++) {
const buf_page_info_t* page_info;
const char* table_name;
const char* index_name;
const char* state_str;
enum buf_page_state state;
table_name = NULL;
index_name = NULL;
state_str = NULL;
page_info = info_array + i;
OK(fields[IDX_BUF_LRU_POOL_ID]->store(page_info->pool_id));
OK(fields[IDX_BUF_LRU_POS]->store(page_info->block_id));
OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(page_info->space_id));
OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(page_info->page_num));
OK(field_store_string(
fields[IDX_BUF_LRU_PAGE_TYPE],
i_s_page_type[page_info->page_type].type_str));
OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(
page_info->flush_type));
OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
page_info->fix_count));
if (page_info->hashed) {
OK(field_store_string(
fields[IDX_BUF_LRU_PAGE_HASHED], "YES"));
} else {
OK(field_store_string(
fields[IDX_BUF_LRU_PAGE_HASHED], "NO"));
}
OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store(
page_info->newest_mod, true));
OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store(
page_info->oldest_mod, true));
OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store(
page_info->access_time));
/* If this is an index page, fetch the index name
and table name */
if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
const dict_index_t* index;
mutex_enter(&dict_sys->mutex);
index = dict_index_get_if_in_cache_low(
page_info->index_id);
/* Copy the index/table name under mutex. We
do not want to hold the InnoDB mutex while
filling the IS table */
if (index) {
const char* name_ptr = index->name;
if (name_ptr[0] == TEMP_INDEX_PREFIX) {
name_ptr++;
}
index_name = mem_heap_strdup(heap, name_ptr);
table_name = mem_heap_strdup(heap,
index->table_name);
}
mutex_exit(&dict_sys->mutex);
}
OK(field_store_string(
fields[IDX_BUF_LRU_PAGE_TABLE_NAME], table_name));
OK(field_store_string(
fields[IDX_BUF_LRU_PAGE_INDEX_NAME], index_name));
OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
page_info->num_recs));
OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store(
page_info->data_size));
OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store(
page_info->zip_ssize ?
512 << page_info->zip_ssize : 0));
state = static_cast<enum buf_page_state>(page_info->page_state);
switch (state) {
/* Compressed page */
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
state_str = "YES";
break;
/* Uncompressed page */
case BUF_BLOCK_FILE_PAGE:
state_str = "NO";
break;
/* We should not see following states */
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
state_str = NULL;
break;
};
OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE],
state_str));
switch (page_info->io_fix) {
case BUF_IO_NONE:
OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
"IO_NONE"));
break;
case BUF_IO_READ:
OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
"IO_READ"));
break;
case BUF_IO_WRITE:
OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
"IO_WRITE"));
break;
}
OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD],
(page_info->is_old) ? "YES" : "NO"));
OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store(
page_info->freed_page_clock));
if (schema_table_store_record(thd, table)) {
mem_heap_free(heap);
DBUG_RETURN(1);
}
mem_heap_empty(heap);
}
mem_heap_free(heap);
DBUG_RETURN(0);
}
/*******************************************************************//**
This is the function that goes through buffer pool's LRU list
and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
@return 0 on success, 1 on failure */
static
int
i_s_innodb_fill_buffer_lru(
/*=======================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
const ulint pool_id) /*!< in: buffer pool id */
{
int status = 0;
buf_page_info_t* info_buffer;
ulint lru_pos = 0;
const buf_page_t* bpage;
ulint lru_len;
DBUG_ENTER("i_s_innodb_fill_buffer_lru");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* Obtain buf_pool mutex before allocate info_buffer, since
UT_LIST_GET_LEN(buf_pool->LRU) could change */
buf_pool_mutex_enter(buf_pool);
lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
/* Print error message if malloc fail */
info_buffer = (buf_page_info_t*) my_malloc(
lru_len * sizeof *info_buffer, MYF(MY_WME));
if (!info_buffer) {
status = 1;
goto exit;
}
memset(info_buffer, 0, lru_len * sizeof *info_buffer);
/* Walk through Pool's LRU list and print the buffer page
information */
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) {
/* Use the same function that collect buffer info for
INNODB_BUFFER_PAGE to get buffer page info */
i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos,
(info_buffer + lru_pos));
bpage = UT_LIST_GET_PREV(LRU, bpage);
lru_pos++;
}
ut_ad(lru_pos == lru_len);
ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
exit:
buf_pool_mutex_exit(buf_pool);
if (info_buffer) {
status = i_s_innodb_buf_page_lru_fill(
thd, tables, info_buffer, lru_len);
my_free(info_buffer);
}
DBUG_RETURN(status);
}
/*******************************************************************//**
Fill page information for pages in InnoDB buffer pool to the
dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
@return 0 on success, 1 on failure */
static
int
i_s_innodb_buf_page_lru_fill_table(
/*===============================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (ignored) */
{
int status = 0;
DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table");
/* deny access to any users that do not hold PROCESS_ACL */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
/* Walk through each buffer pool */
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
/* Fetch information from pages in this buffer pool's LRU list,
and fill the corresponding I_S table */
status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i);
/* If something wrong, break and return */
if (status) {
break;
}
}
DBUG_RETURN(status);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
@return 0 on success, 1 on failure */
static
int
i_s_innodb_buffer_page_lru_init(
/*============================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("i_s_innodb_buffer_page_lru_init");
schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
schema->fields_info = i_s_innodb_buf_page_lru_fields_info;
schema->fill_table = i_s_innodb_buf_page_lru_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page_lru =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD(__reserved1, NULL),
/* Plugin flags */
/* unsigned long */
STRUCT_FLD(flags, 0UL),
};
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
static
int
i_s_common_deinit(
/*==============*/
void* p) /*!< in/out: table schema object */
{
DBUG_ENTER("i_s_common_deinit");
/* Do nothing */
DBUG_RETURN(0);
}