MDEV-7109: Add support for INFORMATION_SCHEMA.INNODB_SEMAPHORE_WAITS

MDEV-7399: Add support for INFORMATION_SCHEMA.INNODB_MUTEXES
    MDEV-7618: Improve semaphore instrumentation

    Introduced two new information schema tables to monitor mutex waits
    and semaphore waits. Added a new configuration variable
    innodb_intrument_semaphores to add thread_id, file name and
    line of current holder of mutex/rw_lock.
This commit is contained in:
Jan Lindström 2015-02-21 21:45:16 +02:00
parent 9152b83973
commit 1cc7befc14
39 changed files with 2173 additions and 293 deletions

View file

@ -24,6 +24,7 @@ INNODB_CMPMEM_RESET
INNODB_CMP_PER_INDEX
INNODB_CMP_RESET
INNODB_LOCK_WAITS
INNODB_MUTEXES
INNODB_SYS_COLUMNS
INNODB_SYS_FIELDS
INNODB_SYS_FOREIGN
@ -97,6 +98,7 @@ INNODB_CMPMEM_RESET page_size
INNODB_CMP_PER_INDEX database_name
INNODB_CMP_RESET page_size
INNODB_LOCK_WAITS requesting_trx_id
INNODB_MUTEXES NAME
INNODB_SYS_COLUMNS TABLE_ID
INNODB_SYS_FIELDS INDEX_ID
INNODB_SYS_FOREIGN ID
@ -170,6 +172,7 @@ INNODB_CMPMEM_RESET page_size
INNODB_CMP_PER_INDEX database_name
INNODB_CMP_RESET page_size
INNODB_LOCK_WAITS requesting_trx_id
INNODB_MUTEXES NAME
INNODB_SYS_COLUMNS TABLE_ID
INNODB_SYS_FIELDS INDEX_ID
INNODB_SYS_FOREIGN ID
@ -248,6 +251,7 @@ INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1
INNODB_CMP_PER_INDEX information_schema.INNODB_CMP_PER_INDEX 1
INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1
INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
INNODB_MUTEXES information_schema.INNODB_MUTEXES 1
INNODB_SYS_COLUMNS information_schema.INNODB_SYS_COLUMNS 1
INNODB_SYS_FIELDS information_schema.INNODB_SYS_FIELDS 1
INNODB_SYS_FOREIGN information_schema.INNODB_SYS_FOREIGN 1
@ -311,6 +315,7 @@ Database: information_schema
| INNODB_CMP_PER_INDEX |
| INNODB_CMP_RESET |
| INNODB_LOCK_WAITS |
| INNODB_MUTEXES |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_FIELDS |
| INNODB_SYS_FOREIGN |
@ -374,6 +379,7 @@ Database: INFORMATION_SCHEMA
| INNODB_CMP_PER_INDEX |
| INNODB_CMP_RESET |
| INNODB_LOCK_WAITS |
| INNODB_MUTEXES |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_FIELDS |
| INNODB_SYS_FOREIGN |
@ -417,5 +423,5 @@ Wildcard: inf_rmation_schema
| information_schema |
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA;
table_schema count(*)
information_schema 58
information_schema 59
mysql 30

View file

@ -0,0 +1,21 @@
create table t1(a int not null primary key, b int, c int,d CHAR(100)) engine=innodb;
create procedure innodb_insert_proc (repeat_count int)
begin
declare current_num int;
set current_num = 0;
while current_num < repeat_count do
insert into t1 values(current_num, RAND(), RAND(), substring(MD5(RAND()), -64));
set current_num = current_num + 1;
end while;
end//
commit;
set autocommit=0;
call innodb_insert_proc(20000);
commit;
set autocommit=1;
delete from t1 where a between 1000 and 1300;
update t1 set b=b+1 where a between 2000 and 2600;
insert into t1 select a+30000,b,c,d from t1 where a between 3000 and 4000;
delete from t1 where a between 6000 and 7000;
drop procedure innodb_insert_proc;
drop table t1;

View file

@ -0,0 +1,26 @@
# Establish connection con1 (user=root)
# Establish connection con2 (user=root)
drop table if exists t1;
# Switch to connection con1
create table t1 (id integer, x integer) engine = InnoDB;
insert into t1 values(0, 0);
set DEBUG_DBUG='+d,fatal-semaphore-timeout';
set autocommit=0;
# Sending query on con1,
# the session will hold lock table mutex and sleep
SELECT * from t1 where id = 0 FOR UPDATE;
# Switch to connection con2
set autocommit=0;
# Sending query on con2,
# the session will be blocked on the lock table mutex and
# thus be put into sync arry
SELECT * from t1 where id = 0 FOR UPDATE;
# Switched to the default connection
# Waitting for mysqld to crash
# Mysqld crash was detected
# Waitting for reconnect after mysqld restarts
# Reconnected after mysqld was successfully restarted
# Cleaning up before exit
set DEBUG_DBUG=NULL;
drop table if exists t1;
# Clean exit

View file

@ -0,0 +1 @@
--innodb-mutexes

View file

@ -0,0 +1,66 @@
--source include/have_innodb.inc
connect(con1,localhost,root,,);
connect(con2,localhost,root,,);
connect(con3,localhost,root,,);
create table t1(a int not null primary key, b int, c int,d CHAR(100)) engine=innodb;
delimiter //;
create procedure innodb_insert_proc (repeat_count int)
begin
declare current_num int;
set current_num = 0;
while current_num < repeat_count do
insert into t1 values(current_num, RAND(), RAND(), substring(MD5(RAND()), -64));
set current_num = current_num + 1;
end while;
end//
delimiter ;//
commit;
set autocommit=0;
call innodb_insert_proc(20000);
commit;
set autocommit=1;
connection con1;
send delete from t1 where a between 1000 and 1300;
connection con2;
send update t1 set b=b+1 where a between 2000 and 2600;
connection con3;
send insert into t1 select a+30000,b,c,d from t1 where a between 3000 and 4000;
connection default;
send delete from t1 where a between 6000 and 7000;
connection con1;
reap;
connection con2;
reap;
connection con3;
reap;
connection default;
reap;
disconnect con1;
disconnect con2;
disconnect con3;
# test that below does not crash, actual result is not
# repeatable
--disable_query_log
--disable_result_log
--disable_warnings
select * from information_schema.innodb_mutexes;
--enable_query_log
--enable_result_log
--enable_warnings
drop procedure innodb_insert_proc;
drop table t1;

View file

@ -0,0 +1,3 @@
--innodb-fatal-semaphore-wait-threshold=1
--innodb-sys-semaphore-waits=1
--innodb-instrument-semaphores=1

View file

@ -0,0 +1,119 @@
--source include/have_innodb.inc
--source include/not_windows.inc
--source include/not_valgrind.inc
--source include/not_embedded.inc
# DEBUG_SYNC must be compiled in.
--source include/have_debug_sync.inc
--echo # Establish connection con1 (user=root)
connect (con1,localhost,root,,);
--echo # Establish connection con2 (user=root)
connect (con2,localhost,root,,);
--disable_warnings
drop table if exists t1;
--enable_warnings
--echo # Switch to connection con1
connection con1;
eval create table t1 (id integer, x integer) engine = InnoDB;
insert into t1 values(0, 0);
# Enable the debug injection.
set DEBUG_DBUG='+d,fatal-semaphore-timeout';
set autocommit=0;
# The following query will hang for an hour since the debug injection
# code will sleep an hour after holding the lock table mutex
--echo # Sending query on con1,
--echo # the session will hold lock table mutex and sleep
--send
SELECT * from t1 where id = 0 FOR UPDATE;
# To make sure con1 holding the lock table mutex and sleeping
--sleep 2
--echo # Switch to connection con2
connection con2;
set autocommit=0;
# The following query will be blocked on the lock table mutex held by
# con1 so it will be put into sync array.
--echo # Sending query on con2,
--echo # the session will be blocked on the lock table mutex and
--echo # thus be put into sync arry
--send
SELECT * from t1 where id = 0 FOR UPDATE;
# Waitting for mysqld to abort due to fatal semaphore timeout.
# Please note that, in the master.opt file, the fatal timeout
# was set to 1 second, but in mysqld debug mode, this timeout
# value will be timed 10 because UNIV_DEBUG_VALGRIND is set
# (see sync_array_print_long_waits_low() in storage/innobase/sync/sync0arr.cc)
# so the actual timeout will be 1 * 10 = 10 seconds. Besides,
# mysqld will abort after detecting this fatal timeout 10 times in
# a loop with interval of 1 second (see srv_error_monitor_thread
# thread in torage/innobase/srv/srv0srv.cc), so mysqld will abort
# in 1 * 10 + 1 * 10 = 20 seconds after con2 being blocked on
# the lock table mutex.
#
# P.S. the default fatal sempahore timeout is 600 seconds,
# so mysqld will abort after 600 * 10 + 1 * 10 = 6010 seconds
# in debug mode and 600 + 1 * 10 = 610 seconds in release mode.
--echo # Switched to the default connection
connection default;
--disable_result_log
--disable_query_log
# Since this test generates lot of errors in log, suppress checking errors
call mtr.add_suppression(".*");
# The crash is expected
exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
--echo # Waitting for mysqld to crash
# It will take 20 seconds to detect the long semaphore and mysqld to abort.
# This test will be treated as pass as long as mysqld crash/restart is dectected
# in 60 seconds.
let $counter= 60;
let $mysql_errno= 0;
while (!$mysql_errno)
{
--error 0,1040,1053,2002,2003,2006,2013
show status;
--error 0,1040,1053,2002,2003,2006,2013
select * from information_schema.innodb_sys_semaphore_waits;
dec $counter;
if (!$counter)
{
# This will fail this test.
--die Server failed to dissapear
}
--sleep 1
}
--echo # Mysqld crash was detected
--echo # Waitting for reconnect after mysqld restarts
enable_reconnect;
connection default;
--exec echo "restart:--log-error=$error_log" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
# Call script that will poll the server waiting for it to be back online again
source include/wait_until_connected_again.inc;
--echo # Reconnected after mysqld was successfully restarted
--echo # Cleaning up before exit
--disable_warnings
set DEBUG_DBUG=NULL;
drop table if exists t1;
--enable_warnings
--echo # Clean exit

View file

@ -10,6 +10,7 @@ there should be *no* long test name listed below:
select distinct variable_name as `there should be *no* variables listed below:` from t2
left join t1 on variable_name=test_name where test_name is null;
there should be *no* variables listed below:
innodb_instrument_semaphores
strict_password_validation
drop table t1;
drop table t2;

View file

@ -0,0 +1,45 @@
#
# innodb_instrument_semaphores
#
# save the initial value
SET @innodb_instrument_semaphores_global_saved = @@global.innodb_instrument_semaphores;
# default
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
0
# scope
SELECT @@session.innodb_instrument_semaphores;
ERROR HY000: Variable 'innodb_instrument_semaphores' is a GLOBAL variable
SET @@global.innodb_instrument_semaphores=OFF;
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
0
SET @@global.innodb_instrument_semaphores=ON;
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
1
# valid values
SET @@global.innodb_instrument_semaphores='OFF';
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
0
SET @@global.innodb_instrument_semaphores=ON;
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
1
SET @@global.innodb_instrument_semaphores=default;
SELECT @@global.innodb_instrument_semaphores;
@@global.innodb_instrument_semaphores
0
# invalid values
SET @@global.innodb_instrument_semaphores=NULL;
ERROR 42000: Variable 'innodb_instrument_semaphores' can't be set to the value of 'NULL'
SET @@global.innodb_instrument_semaphores='junk';
ERROR 42000: Variable 'innodb_instrument_semaphores' can't be set to the value of 'junk'
# restore the initial value
SET @@global.innodb_instrument_semaphores = @innodb_instrument_semaphores_global_saved;
# End of test

View file

@ -1209,6 +1209,20 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_INSTRUMENT_SEMAPHORES
SESSION_VALUE NULL
GLOBAL_VALUE OFF
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Enable semaphore request instrumentation. This could have some effect on performance but allows better information on long semaphore wait problems. (Default: not enabled)
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_IO_CAPACITY
SESSION_VALUE NULL
GLOBAL_VALUE 200

View file

@ -0,0 +1,42 @@
--source include/have_innodb.inc
--echo #
--echo # innodb_instrument_semaphores
--echo #
--echo # save the initial value
SET @innodb_instrument_semaphores_global_saved = @@global.innodb_instrument_semaphores;
--echo # default
SELECT @@global.innodb_instrument_semaphores;
--echo
--echo # scope
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT @@session.innodb_instrument_semaphores;
SET @@global.innodb_instrument_semaphores=OFF;
SELECT @@global.innodb_instrument_semaphores;
SET @@global.innodb_instrument_semaphores=ON;
SELECT @@global.innodb_instrument_semaphores;
--echo
--echo # valid values
SET @@global.innodb_instrument_semaphores='OFF';
SELECT @@global.innodb_instrument_semaphores;
SET @@global.innodb_instrument_semaphores=ON;
SELECT @@global.innodb_instrument_semaphores;
SET @@global.innodb_instrument_semaphores=default;
SELECT @@global.innodb_instrument_semaphores;
--echo
--echo # invalid values
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.innodb_instrument_semaphores=NULL;
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.innodb_instrument_semaphores='junk';
--echo
--echo # restore the initial value
SET @@global.innodb_instrument_semaphores = @innodb_instrument_semaphores_global_saved;
--echo # End of test

View file

@ -13,5 +13,6 @@
--loose-innodb-sys-foreign-cols
--loose-innodb-sys-tables
--loose-innodb-sys-tablestats
--loose-innodb-mutexes
--loose-innodb-tablespaces-encryption
--loose-innodb-tablespaces-scrubbing

View file

@ -19221,6 +19221,12 @@ static MYSQL_SYSVAR_BOOL(scrub_force_testing,
NULL, NULL, FALSE);
#endif /* UNIV_DEBUG */
static MYSQL_SYSVAR_BOOL(instrument_semaphores, srv_instrument_semaphores,
PLUGIN_VAR_OPCMDARG,
"Enable semaphore request instrumentation. This could have some effect on performance but allows better"
" information on long semaphore wait problems. (Default: not enabled)",
0, 0, FALSE);
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(api_trx_level),
@ -19418,6 +19424,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(scrub_force_testing),
#endif
MYSQL_SYSVAR(instrument_semaphores),
NULL
};
@ -19465,6 +19472,8 @@ i_s_innodb_sys_foreign,
i_s_innodb_sys_foreign_cols,
i_s_innodb_sys_tablespaces,
i_s_innodb_sys_datafiles,
i_s_innodb_mutexes,
i_s_innodb_sys_semaphore_waits,
i_s_innodb_tablespaces_encryption,
i_s_innodb_tablespaces_scrubbing
maria_declare_plugin_end;

View file

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyrigth (c) 2014, 2015, MariaDB Corporation
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
@ -21,8 +22,11 @@ this program; if not, write to the Free Software Foundation, Inc.,
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits)
*******************************************************/
#include "univ.i"
#include <mysqld_error.h>
#include <sql_acl.h>
@ -56,6 +60,7 @@ Created July 18, 2007 Vasil Dimov
#include "fts0priv.h"
#include "btr0btr.h"
#include "page0zip.h"
#include "sync0arr.h"
/** structure associates a name string with a file page type and/or buffer
page state. */
@ -137,45 +142,6 @@ struct buf_page_info_t{
index_id_t index_id; /*!< Index ID if a index page */
};
/** 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, Sql_condition::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 && !defined __clang__
#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:
@ -204,6 +170,20 @@ time_t MYSQL_TYPE_DATETIME
---------------------------------
*/
/** Implemented on sync0arr.cc */
/*******************************************************************//**
Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
Loop through each item on sync array, and extract the column
information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
@return 0 on success */
UNIV_INTERN
int
sync_arr_fill_sys_semphore_waits_table(
/*===================================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ); /*!< in: condition (not used) */
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@ -261,7 +241,6 @@ field_store_time_t(
/*******************************************************************//**
Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
@return 0 on success */
static
int
field_store_string(
/*===============*/
@ -328,7 +307,6 @@ field_store_index_name(
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(
/*==============*/
@ -8654,3 +8632,494 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_scrubbing =
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
};
/** INNODB_MUTEXES *********************************************/
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES */
static ST_FIELD_INFO innodb_mutexes_fields_info[] =
{
#define MUTEXES_NAME 0
{STRUCT_FLD(field_name, "NAME"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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 MUTEXES_CREATE_FILE 1
{STRUCT_FLD(field_name, "CREATE_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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 MUTEXES_CREATE_LINE 2
{STRUCT_FLD(field_name, "CREATE_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define MUTEXES_OS_WAITS 3
{STRUCT_FLD(field_name, "OS_WAITS"),
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
};
/*******************************************************************//**
Function to populate INFORMATION_SCHEMA.INNODB_MUTEXES table.
Loop through each record in mutex and rw_lock lists, and extract the column
information and fill the INFORMATION_SCHEMA.INNODB_MUTEXES table.
@return 0 on success */
static
int
i_s_innodb_mutexes_fill_table(
/*==========================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (not used) */
{
ib_mutex_t* mutex;
rw_lock_t* lock;
ulint block_mutex_oswait_count = 0;
ulint block_lock_oswait_count = 0;
ib_mutex_t* block_mutex = NULL;
rw_lock_t* block_lock = NULL;
Field** fields = tables->table->field;
DBUG_ENTER("i_s_innodb_mutexes_fill_table");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* deny access to user without PROCESS_ACL privilege */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
mutex_enter(&mutex_list_mutex);
for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
mutex = UT_LIST_GET_NEXT(list, mutex)) {
if (mutex->count_os_wait == 0) {
continue;
}
if (buf_pool_is_block_mutex(mutex)) {
block_mutex = mutex;
block_mutex_oswait_count += mutex->count_os_wait;
continue;
}
OK(field_store_string(fields[MUTEXES_NAME], mutex->cmutex_name));
OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(mutex->cfile_name)));
OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], mutex->cline));
OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)mutex->count_os_wait));
OK(schema_table_store_record(thd, tables->table));
}
if (block_mutex) {
char buf1[IO_SIZE];
my_snprintf(buf1, sizeof buf1, "combined %s",
innobase_basename(block_mutex->cfile_name));
OK(field_store_string(fields[MUTEXES_NAME], block_mutex->cmutex_name));
OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1));
OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], block_mutex->cline));
OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)block_mutex_oswait_count));
OK(schema_table_store_record(thd, tables->table));
}
mutex_exit(&mutex_list_mutex);
mutex_enter(&rw_lock_list_mutex);
for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
lock = UT_LIST_GET_NEXT(list, lock)) {
if (lock->count_os_wait == 0) {
continue;
}
if (buf_pool_is_block_lock(lock)) {
block_lock = lock;
block_lock_oswait_count += lock->count_os_wait;
continue;
}
OK(field_store_string(fields[MUTEXES_NAME], lock->lock_name));
OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(lock->cfile_name)));
OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], lock->cline));
OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)lock->count_os_wait));
OK(schema_table_store_record(thd, tables->table));
}
if (block_lock) {
char buf1[IO_SIZE];
my_snprintf(buf1, sizeof buf1, "combined %s",
innobase_basename(block_lock->cfile_name));
OK(field_store_string(fields[MUTEXES_NAME], block_lock->lock_name));
OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1));
OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], block_lock->cline));
OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)block_lock_oswait_count));
OK(schema_table_store_record(thd, tables->table));
}
mutex_exit(&rw_lock_list_mutex);
DBUG_RETURN(0);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES
@return 0 on success */
static
int
innodb_mutexes_init(
/*================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_mutexes_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = innodb_mutexes_fields_info;
schema->fill_table = i_s_innodb_mutexes_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_maria_plugin i_s_innodb_mutexes =
{
/* 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_MUTEXES"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB SYS_DATAFILES"),
/* 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_mutexes_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),
/* Maria extension */
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
};
/** SYS_SEMAPHORE_WAITS ************************************************/
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS */
static ST_FIELD_INFO innodb_sys_semaphore_waits_fields_info[] =
{
// SYS_SEMAPHORE_WAITS_THREAD_ID 0
{STRUCT_FLD(field_name, "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)},
// SYS_SEMAPHORE_WAITS_OBJECT_NAME 1
{STRUCT_FLD(field_name, "OBJECT_NAME"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_FILE 2
{STRUCT_FLD(field_name, "FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_LINE 3
{STRUCT_FLD(field_name, "LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_WAIT_TIME 4
{STRUCT_FLD(field_name, "WAIT_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)},
// SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5
{STRUCT_FLD(field_name, "WAIT_OBJECT"),
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)},
// SYS_SEMAPHORE_WAITS_WAIT_TYPE 6
{STRUCT_FLD(field_name, "WAIT_TYPE"),
STRUCT_FLD(field_length, 16),
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)},
// SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7
{STRUCT_FLD(field_name, "HOLDER_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)},
// SYS_SEMAPHORE_WAITS_HOLDER_FILE 8
{STRUCT_FLD(field_name, "HOLDER_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_HOLDER_LINE 9
{STRUCT_FLD(field_name, "HOLDER_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_CREATED_FILE 10
{STRUCT_FLD(field_name, "CREATED_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_CREATED_LINE 11
{STRUCT_FLD(field_name, "CREATED_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_WRITER_THREAD 12
{STRUCT_FLD(field_name, "WRITER_THREAD"),
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)},
// SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13
{STRUCT_FLD(field_name, "RESERVATION_MODE"),
STRUCT_FLD(field_length, 16),
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)},
// SYS_SEMAPHORE_WAITS_READERS 14
{STRUCT_FLD(field_name, "READERS"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15
{STRUCT_FLD(field_name, "WAITERS_FLAG"),
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)},
// SYS_SEMAPHORE_WAITS_LOCK_WORD 16
{STRUCT_FLD(field_name, "LOCK_WORD"),
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)},
// SYS_SEMAPHORE_WAITS_LAST_READER_FILE 17
{STRUCT_FLD(field_name, "LAST_READER_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_LAST_READER_LINE 18
{STRUCT_FLD(field_name, "LAST_READER_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 19
{STRUCT_FLD(field_name, "LAST_WRITER_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 20
{STRUCT_FLD(field_name, "LAST_WRITER_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 21
{STRUCT_FLD(field_name, "OS_WAIT_COUNT"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
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
};
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS
@return 0 on success */
static
int
innodb_sys_semaphore_waits_init(
/*============================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_sys_semaphore_waits_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = innodb_sys_semaphore_waits_fields_info;
schema->fill_table = sync_arr_fill_sys_semphore_waits_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_semaphore_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_SYS_SEMAPHORE_WAITS"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, maria_plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB SYS_SEMAPHORE_WAITS"),
/* 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_sys_semaphore_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),
/* Maria extension */
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
};

View file

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyrigth (c) 2014, 2015, MariaDB Corporation
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
@ -21,12 +22,14 @@ this program; if not, write to the Free Software Foundation, Inc.,
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
Modified Dec 29, 2014 Jan Lindström
*******************************************************/
#ifndef i_s_h
#define i_s_h
const char plugin_author[] = "Oracle Corporation";
const char maria_plugin_author[] = "MariaDB Corporation";
extern struct st_maria_plugin i_s_innodb_trx;
extern struct st_maria_plugin i_s_innodb_locks;
@ -56,7 +59,92 @@ extern struct st_maria_plugin i_s_innodb_sys_foreign;
extern struct st_maria_plugin i_s_innodb_sys_foreign_cols;
extern struct st_maria_plugin i_s_innodb_sys_tablespaces;
extern struct st_maria_plugin i_s_innodb_sys_datafiles;
extern struct st_maria_plugin i_s_innodb_mutexes;
extern struct st_maria_plugin i_s_innodb_tablespaces_encryption;
extern struct st_maria_plugin i_s_innodb_tablespaces_scrubbing;
extern struct st_maria_plugin i_s_innodb_sys_semaphore_waits;
/** 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, Sql_condition::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 && !defined __clang__
#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)}
/** Fields on INFORMATION_SCHEMA.SYS_SEMAMPHORE_WAITS table */
#define SYS_SEMAPHORE_WAITS_THREAD_ID 0
#define SYS_SEMAPHORE_WAITS_OBJECT_NAME 1
#define SYS_SEMAPHORE_WAITS_FILE 2
#define SYS_SEMAPHORE_WAITS_LINE 3
#define SYS_SEMAPHORE_WAITS_WAIT_TIME 4
#define SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5
#define SYS_SEMAPHORE_WAITS_WAIT_TYPE 6
#define SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7
#define SYS_SEMAPHORE_WAITS_HOLDER_FILE 8
#define SYS_SEMAPHORE_WAITS_HOLDER_LINE 9
#define SYS_SEMAPHORE_WAITS_CREATED_FILE 10
#define SYS_SEMAPHORE_WAITS_CREATED_LINE 11
#define SYS_SEMAPHORE_WAITS_WRITER_THREAD 12
#define SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13
#define SYS_SEMAPHORE_WAITS_READERS 14
#define SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15
#define SYS_SEMAPHORE_WAITS_LOCK_WORD 16
#define SYS_SEMAPHORE_WAITS_LAST_READER_FILE 17
#define SYS_SEMAPHORE_WAITS_LAST_READER_LINE 18
#define SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 19
#define SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 20
#define SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 21
/*******************************************************************//**
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 */
int
field_store_ulint(
/*==============*/
Field* field, /*!< in/out: target field for storage */
ulint n); /*!< in: value to store */
/*******************************************************************//**
Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
@return 0 on success */
int
field_store_string(
/*===============*/
Field* field, /*!< in/out: target field for storage */
const char* str); /*!< in: NUL-terminated utf-8 string,
or NULL */
#endif /* i_s_h */

View file

@ -565,6 +565,9 @@ extern ulong srv_fatal_semaphore_wait_threshold;
/** Default encryption key used for page encryption */
extern uint srv_default_page_encryption_key;
/** Enable semaphore request instrumentation */
extern my_bool srv_instrument_semaphores;
# ifdef UNIV_PFS_THREAD
/* Keys to register InnoDB threads with performance schema */
extern mysql_pfs_key_t buf_page_cleaner_thread_key;

View file

@ -31,7 +31,7 @@ Created 9/5/1995 Heikki Tuuri
#include "ut0mem.h"
#include "os0thread.h"
/** Synchronization wait array cell */
/** Synchonization cell */
struct sync_cell_t;
/** Synchronization wait array */
struct sync_array_t;
@ -154,6 +154,16 @@ UNIV_INTERN
void
sync_array_print_innodb(void);
/*****************************************************************//**
Gets the nth cell in array.
@return cell */
UNIV_INTERN
sync_cell_t*
sync_array_get_nth_cell(
/*====================*/
sync_array_t* arr, /*!< in: sync array */
ulint n); /*!< in: index */
#ifndef UNIV_NONINL
#include "sync0arr.ic"
#endif

View file

@ -40,6 +40,9 @@ Created 9/11/1995 Heikki Tuuri
#include "sync0sync.h"
#include "os0sync.h"
/** Enable semaphore request instrumentation */
extern my_bool srv_instrument_semaphores;
/* The following undef is to prevent a name conflict with a macro
in MySQL: */
#undef rw_lock_t
@ -224,7 +227,7 @@ unlocking, not the corresponding function. */
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
/******************************************************************
@ -294,8 +297,8 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
@ -610,6 +613,10 @@ struct rw_lock_t {
#endif
ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
const char* cfile_name;/*!< File name where lock created */
const char* lock_name; /*!< lock name */
os_thread_id_t thread_id;/*!< thread id */
const char* file_name;/*!< File name where the lock was obtained */
ulint line; /*!< Line where the rw-lock was locked */
/* last s-lock file/line is not guaranteed to be correct */
const char* last_s_file_name;/*!< File name where last s-locked */
const char* last_x_file_name;/*!< File name where last x-locked */
@ -688,8 +695,8 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */

View file

@ -325,6 +325,12 @@ rw_lock_s_lock_low(
lock->last_s_file_name = file_name;
lock->last_s_line = line;
if (srv_instrument_semaphores) {
lock->thread_id = os_thread_get_curr_id();
lock->file_name = file_name;
lock->line = line;
}
return(TRUE); /* locking succeeded */
}
@ -426,6 +432,12 @@ rw_lock_x_lock_func_nowait(
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
#endif
if (srv_instrument_semaphores) {
lock->thread_id = os_thread_get_curr_id();
lock->file_name = file_name;
lock->line = line;
}
lock->last_x_file_name = file_name;
lock->last_x_line = line;
@ -546,8 +558,8 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
# endif /* UNIV_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
@ -560,8 +572,8 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
cmutex_name,
# endif /* UNIV_DEBUG */
cmutex_name,
cfile_name,
cline);
}

View file

@ -42,6 +42,9 @@ Created 9/5/1995 Heikki Tuuri
#include "os0sync.h"
#include "sync0arr.h"
/** Enable semaphore request instrumentation */
extern my_bool srv_instrument_semaphores;
#if defined(UNIV_DEBUG) && !defined(UNIV_HOTBACKUP)
extern "C" my_bool timed_mutexes;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
@ -180,7 +183,7 @@ necessary only if the memory block containing it is freed. */
# endif/* UNIV_SYNC_DEBUG */
# else
# define mutex_create(K, M, level) \
pfs_mutex_create_func((K), (M), __FILE__, __LINE__)
pfs_mutex_create_func((K), (M), #M, __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
# define mutex_enter(M) \
@ -231,8 +234,8 @@ void
mutex_create_func(
/*==============*/
ib_mutex_t* mutex, /*!< in: pointer to memory */
#ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@ -305,8 +308,8 @@ pfs_mutex_create_func(
/*==================*/
PSI_mutex_key key, /*!< in: Performance Schema key */
ib_mutex_t* mutex, /*!< in: pointer to memory */
# ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@ -763,22 +766,22 @@ struct ib_mutex_t {
UT_LIST_NODE_T(ib_mutex_t) list; /*!< All allocated mutexes are put into
a list. Pointers to the next and prev. */
#ifdef UNIV_SYNC_DEBUG
const char* file_name; /*!< File where the mutex was locked */
ulint line; /*!< Line where the mutex was locked */
ulint level; /*!< Level in the global latching order */
#endif /* UNIV_SYNC_DEBUG */
const char* file_name; /*!< File where the mutex was locked */
ulint line; /*!< Line where the mutex was locked */
const char* cfile_name;/*!< File name where mutex created */
ulint cline; /*!< Line where created */
ulong count_os_wait; /*!< count of os_wait */
const char* cmutex_name; /*!< mutex name */
os_thread_id_t thread_id; /*!< The thread id of the thread
which locked the mutex. */
#ifdef UNIV_DEBUG
/** Value of mutex_t::magic_n */
# define MUTEX_MAGIC_N 979585UL
os_thread_id_t thread_id; /*!< The thread id of the thread
which locked the mutex. */
ulint magic_n; /*!< MUTEX_MAGIC_N */
const char* cmutex_name; /*!< mutex name */
ulint ib_mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
#endif /* UNIV_DEBUG */
#ifdef UNIV_PFS_MUTEX

View file

@ -162,7 +162,7 @@ mutex_exit_func(
{
ut_ad(mutex_own(mutex));
ut_d(mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED);
mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED;
#ifdef UNIV_SYNC_DEBUG
sync_thread_reset_level(mutex);
@ -213,10 +213,15 @@ mutex_enter_func(
the atomic test_and_set; we could peek, and possibly save time. */
if (!ib_mutex_test_and_set(mutex)) {
ut_d(mutex->thread_id = os_thread_get_curr_id());
mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
if (srv_instrument_semaphores) {
mutex->file_name = file_name;
mutex->line = line;
}
return; /* Succeeded! */
}
@ -324,8 +329,8 @@ pfs_mutex_create_func(
/*==================*/
mysql_pfs_key_t key, /*!< in: Performance Schema key */
ib_mutex_t* mutex, /*!< in: pointer to memory */
# ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@ -336,8 +341,8 @@ pfs_mutex_create_func(
mutex->pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex);
mutex_create_func(mutex,
# ifdef UNIV_DEBUG
cmutex_name,
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */

View file

@ -76,6 +76,7 @@ Created 10/8/1995 Heikki Tuuri
#include "fil0fil.h"
#include "fil0pagecompress.h"
#include "btr0scrub.h"
#include "fil0pageencryption.h"
#ifdef WITH_WSREP
extern int wsrep_debug;
@ -523,7 +524,10 @@ second. */
static time_t srv_last_log_flush_time;
/** Default encryption key used for page encryption */
UNIV_INTERN uint srv_default_page_encryption_key;
UNIV_INTERN uint srv_default_page_encryption_key = DEFAULT_ENCRYPTION_KEY;
/** Enable semaphore request instrumentation */
UNIV_INTERN my_bool srv_instrument_semaphores = FALSE;
/* Interval in seconds at which various tasks are performed by the
master thread when server is active. In order to balance the workload,

View file

@ -2,6 +2,7 @@
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -30,11 +31,26 @@ The wait array used in synchronization primitives
Created 9/5/1995 Heikki Tuuri
*******************************************************/
#include "univ.i"
#include "sync0arr.h"
#ifdef UNIV_NONINL
#include "sync0arr.ic"
#endif
#include <mysqld_error.h>
#include <mysql/plugin.h>
#include <hash.h>
#include <myisampack.h>
#include <sql_acl.h>
#include <mysys_err.h>
#include <my_sys.h>
#include "srv0srv.h"
#include "srv0start.h"
#include "i_s.h"
#include <sql_plugin.h>
#include <innodb_priv.h>
#include "sync0sync.h"
#include "sync0rw.h"
#include "os0sync.h"
@ -115,7 +131,6 @@ for an event allocated for the array without owning the
protecting mutex (depending on the case: OS or database mutex), but
all changes (set or reset) to the state of the event must be made
while owning the mutex. */
/** Synchronization array */
struct sync_array_t {
ulint n_reserved; /*!< number of currently reserved
@ -168,7 +183,6 @@ sync_array_detect_deadlock(
/*****************************************************************//**
Gets the nth cell in array.
@return cell */
static
sync_cell_t*
sync_array_get_nth_cell(
/*====================*/
@ -507,7 +521,7 @@ sync_array_cell_print(
: type == RW_LOCK_WAIT_EX ? "X-lock (wait_ex) on"
: "S-lock on", file);
rwlock = cell->old_wait_rw_lock;
rwlock = (rw_lock_t*)cell->old_wait_rw_lock;
if (rwlock) {
fprintf(file,
@ -1282,3 +1296,153 @@ sync_array_print_innodb(void)
fputs("InnoDB: Semaphore wait debug output ended:\n", stderr);
}
/**********************************************************************//**
Get number of items on sync array. */
UNIV_INTERN
ulint
sync_arr_get_n_items(void)
/*======================*/
{
sync_array_t* sync_arr = sync_array_get();
return (ulint) sync_arr->n_cells;
}
/******************************************************************//**
Get specified item from sync array if it is reserved. Set given
pointer to array item if it is reserved.
@return true if item is reserved, false othervise */
UNIV_INTERN
ibool
sync_arr_get_item(
/*==============*/
ulint i, /*!< in: requested item */
sync_cell_t **cell) /*!< out: cell contents if item
reserved */
{
sync_array_t* sync_arr;
sync_cell_t* wait_cell;
void* wait_object;
ibool found = FALSE;
sync_arr = sync_array_get();
wait_cell = sync_array_get_nth_cell(sync_arr, i);
if (wait_cell) {
wait_object = wait_cell->wait_object;
if(wait_object != NULL && wait_cell->waiting) {
found = TRUE;
*cell = wait_cell;
}
}
return found;
}
/*******************************************************************//**
Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
Loop through each item on sync array, and extract the column
information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
@return 0 on success */
UNIV_INTERN
int
sync_arr_fill_sys_semphore_waits_table(
/*===================================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (not used) */
{
Field** fields;
ulint n_items;
DBUG_ENTER("i_s_sys_semaphore_waits_fill_table");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* deny access to user without PROCESS_ACL privilege */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
fields = tables->table->field;
n_items = sync_arr_get_n_items();
ulint type;
for(ulint i=0; i < n_items;i++) {
sync_cell_t *cell=NULL;
if (sync_arr_get_item(i, &cell)) {
ib_mutex_t* mutex;
type = cell->request_type;
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_THREAD_ID], (longlong)os_thread_pf(cell->thread)));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_FILE], innobase_basename(cell->file)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LINE], cell->line));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_TIME], (longlong)difftime(time(NULL), cell->reservation_time)));
if (type == SYNC_MUTEX) {
mutex = static_cast<ib_mutex_t*>(cell->old_wait_mutex);
if (mutex) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], mutex->cmutex_name));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT], (longlong)mutex));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "MUTEX"));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID], (longlong)mutex->thread_id));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(mutex->file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE], mutex->line));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_CREATED_FILE], innobase_basename(mutex->cfile_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_CREATED_LINE], mutex->cline));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG], (longlong)mutex->waiters));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD], (longlong)mutex->lock_word));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(mutex->file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE], mutex->line));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT], mutex->count_os_wait));
}
} else if (type == RW_LOCK_EX
|| type == RW_LOCK_WAIT_EX
|| type == RW_LOCK_SHARED) {
rw_lock_t* rwlock=NULL;
rwlock = static_cast<rw_lock_t *> (cell->old_wait_rw_lock);
if (rwlock) {
ulint writer = rw_lock_get_writer(rwlock);
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT], (longlong)rwlock));
if (type == RW_LOCK_EX) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_EX"));
} else if (type == RW_LOCK_WAIT_EX) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_WAIT_EX"));
} else if (type == RW_LOCK_SHARED) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_SHARED"));
}
if (writer != RW_LOCK_NOT_LOCKED) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], rwlock->lock_name));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WRITER_THREAD], (longlong)os_thread_pf(rwlock->writer_thread)));
if (writer == RW_LOCK_EX) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_RESERVATION_MODE], "RW_LOCK_EX"));
} else if (writer == RW_LOCK_WAIT_EX) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_RESERVATION_MODE], "RW_LOCK_WAIT_EX"));
}
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID], (longlong)rwlock->thread_id));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(rwlock->file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE], rwlock->line));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_READERS], rw_lock_get_reader_count(rwlock)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG], (longlong)rwlock->waiters));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD], (longlong)rwlock->lock_word));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_READER_FILE], innobase_basename(rwlock->last_s_file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_READER_LINE], rwlock->last_s_line));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(rwlock->last_x_file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE], rwlock->last_x_line));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT], rwlock->count_os_wait));
}
}
}
OK(schema_table_store_record(thd, tables->table));
}
}
DBUG_RETURN(0);
}

View file

@ -209,8 +209,8 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
@ -223,8 +223,7 @@ rw_lock_create_func(
lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline;
ut_d(lock->mutex.cmutex_name = cmutex_name);
lock->mutex.lock_name = cmutex_name;
ut_d(lock->mutex.ib_mutex_type = 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
# ifdef UNIV_DEBUG
@ -253,8 +252,10 @@ rw_lock_create_func(
lock->cfile_name = cfile_name;
lock->cline = (unsigned int) cline;
lock->lock_name = cmutex_name;
lock->count_os_wait = 0;
lock->file_name = "not yet reserved";
lock->line = 0;
lock->last_s_file_name = "not yet reserved";
lock->last_x_file_name = "not yet reserved";
lock->last_s_line = 0;
@ -516,6 +517,12 @@ rw_lock_x_lock_wait(
file_name, line);
#endif
if (srv_instrument_semaphores) {
lock->thread_id = os_thread_get_curr_id();
lock->file_name = file_name;
lock->line = line;
}
sync_array_wait_event(sync_arr, index);
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(
@ -588,6 +595,13 @@ rw_lock_x_lock_low(
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name, line);
#endif
if (srv_instrument_semaphores) {
lock->thread_id = os_thread_get_curr_id();
lock->file_name = file_name;
lock->line = line;
}
lock->last_x_file_name = file_name;
lock->last_x_line = (unsigned int) line;

View file

@ -265,8 +265,8 @@ void
mutex_create_func(
/*==============*/
ib_mutex_t* mutex, /*!< in: pointer to memory */
#ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@ -285,9 +285,10 @@ mutex_create_func(
#ifdef UNIV_DEBUG
mutex->magic_n = MUTEX_MAGIC_N;
#endif /* UNIV_DEBUG */
#ifdef UNIV_SYNC_DEBUG
mutex->line = 0;
mutex->file_name = "not yet reserved";
#ifdef UNIV_SYNC_DEBUG
mutex->level = level;
#endif /* UNIV_SYNC_DEBUG */
mutex->cfile_name = cfile_name;
@ -398,11 +399,15 @@ mutex_enter_nowait_func(
if (!ib_mutex_test_and_set(mutex)) {
ut_d(mutex->thread_id = os_thread_get_curr_id());
mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#else
if (srv_instrument_semaphores) {
mutex->file_name = file_name;
mutex->line = line;
}
#endif
return(0); /* Succeeded! */
}
@ -520,10 +525,15 @@ spin_loop:
if (ib_mutex_test_and_set(mutex) == 0) {
/* Succeeded! */
ut_d(mutex->thread_id = os_thread_get_curr_id());
mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
if (srv_instrument_semaphores) {
mutex->file_name = file_name;
mutex->line = line;
}
return;
}
@ -563,10 +573,14 @@ spin_loop:
sync_array_free_cell(sync_arr, index);
ut_d(mutex->thread_id = os_thread_get_curr_id());
mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
if (srv_instrument_semaphores) {
mutex->file_name = file_name;
mutex->line = line;
}
return;

View file

@ -20412,6 +20412,12 @@ static MYSQL_SYSVAR_BOOL(scrub_force_testing,
NULL, NULL, FALSE);
#endif /* UNIV_DEBUG */
static MYSQL_SYSVAR_BOOL(instrument_semaphores, srv_instrument_semaphores,
PLUGIN_VAR_OPCMDARG,
"Enable semaphore request instrumentation. This could have some effect on performance but allows better"
" information on long semaphore wait problems. (Default: not enabled)",
0, 0, FALSE);
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(log_block_size),
MYSQL_SYSVAR(additional_mem_pool_size),
@ -20646,7 +20652,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(scrub_force_testing),
#endif
MYSQL_SYSVAR(instrument_semaphores),
NULL
};
@ -20698,6 +20704,8 @@ i_s_innodb_sys_foreign_cols,
i_s_innodb_sys_tablespaces,
i_s_innodb_sys_datafiles,
i_s_innodb_changed_pages,
i_s_innodb_mutexes,
i_s_innodb_sys_semaphore_waits,
i_s_innodb_tablespaces_encryption,
i_s_innodb_tablespaces_scrubbing
maria_declare_plugin_end;

View file

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyrigth (c) 2014, 2015, MariaDB Corporation
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
@ -21,7 +22,9 @@ this program; if not, write to the Free Software Foundation, Inc.,
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits)
*******************************************************/
#include "univ.i"
#include <my_global.h>
#ifndef MYSQL_SERVER
#define MYSQL_SERVER /* For Item_* classes */
@ -68,6 +71,7 @@ Created July 18, 2007 Vasil Dimov
#include "log0online.h"
#include "btr0btr.h"
#include "page0zip.h"
#include "sync0arr.h"
/** structure associates a name string with a file page type and/or buffer
page state. */
@ -149,45 +153,6 @@ struct buf_page_info_t{
index_id_t index_id; /*!< Index ID if a index page */
};
/** 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, Sql_condition::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 && !defined __clang__
#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:
@ -216,6 +181,20 @@ time_t MYSQL_TYPE_DATETIME
---------------------------------
*/
/** Implemented on sync0arr.cc */
/*******************************************************************//**
Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
Loop through each item on sync array, and extract the column
information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
@return 0 on success */
UNIV_INTERN
int
sync_arr_fill_sys_semphore_waits_table(
/*===================================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ); /*!< in: condition (not used) */
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@ -273,7 +252,6 @@ field_store_time_t(
/*******************************************************************//**
Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
@return 0 on success */
static
int
field_store_string(
/*===============*/
@ -340,7 +318,6 @@ field_store_index_name(
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(
/*==============*/
@ -8992,3 +8969,494 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_scrubbing =
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
};
/** INNODB_MUTEXES *********************************************/
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES */
static ST_FIELD_INFO innodb_mutexes_fields_info[] =
{
#define MUTEXES_NAME 0
{STRUCT_FLD(field_name, "NAME"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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 MUTEXES_CREATE_FILE 1
{STRUCT_FLD(field_name, "CREATE_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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 MUTEXES_CREATE_LINE 2
{STRUCT_FLD(field_name, "CREATE_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
#define MUTEXES_OS_WAITS 3
{STRUCT_FLD(field_name, "OS_WAITS"),
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
};
/*******************************************************************//**
Function to populate INFORMATION_SCHEMA.INNODB_MUTEXES table.
Loop through each record in mutex and rw_lock lists, and extract the column
information and fill the INFORMATION_SCHEMA.INNODB_MUTEXES table.
@return 0 on success */
static
int
i_s_innodb_mutexes_fill_table(
/*==========================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (not used) */
{
ib_mutex_t* mutex;
rw_lock_t* lock;
ulint block_mutex_oswait_count = 0;
ulint block_lock_oswait_count = 0;
ib_mutex_t* block_mutex = NULL;
rw_lock_t* block_lock = NULL;
Field** fields = tables->table->field;
DBUG_ENTER("i_s_innodb_mutexes_fill_table");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* deny access to user without PROCESS_ACL privilege */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
mutex_enter(&mutex_list_mutex);
for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
mutex = UT_LIST_GET_NEXT(list, mutex)) {
if (mutex->count_os_wait == 0) {
continue;
}
if (buf_pool_is_block_mutex(mutex)) {
block_mutex = mutex;
block_mutex_oswait_count += mutex->count_os_wait;
continue;
}
OK(field_store_string(fields[MUTEXES_NAME], mutex->cmutex_name));
OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(mutex->cfile_name)));
OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], mutex->cline));
OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)mutex->count_os_wait));
OK(schema_table_store_record(thd, tables->table));
}
if (block_mutex) {
char buf1[IO_SIZE];
my_snprintf(buf1, sizeof buf1, "combined %s",
innobase_basename(block_mutex->cfile_name));
OK(field_store_string(fields[MUTEXES_NAME], block_mutex->cmutex_name));
OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1));
OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], block_mutex->cline));
OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)block_mutex_oswait_count));
OK(schema_table_store_record(thd, tables->table));
}
mutex_exit(&mutex_list_mutex);
mutex_enter(&rw_lock_list_mutex);
for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
lock = UT_LIST_GET_NEXT(list, lock)) {
if (lock->count_os_wait == 0) {
continue;
}
if (buf_pool_is_block_lock(lock)) {
block_lock = lock;
block_lock_oswait_count += lock->count_os_wait;
continue;
}
OK(field_store_string(fields[MUTEXES_NAME], lock->lock_name));
OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(lock->cfile_name)));
OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], lock->cline));
OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)lock->count_os_wait));
OK(schema_table_store_record(thd, tables->table));
}
if (block_lock) {
char buf1[IO_SIZE];
my_snprintf(buf1, sizeof buf1, "combined %s",
innobase_basename(block_lock->cfile_name));
OK(field_store_string(fields[MUTEXES_NAME], block_lock->lock_name));
OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1));
OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], block_lock->cline));
OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)block_lock_oswait_count));
OK(schema_table_store_record(thd, tables->table));
}
mutex_exit(&rw_lock_list_mutex);
DBUG_RETURN(0);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES
@return 0 on success */
static
int
innodb_mutexes_init(
/*================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_mutexes_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = innodb_mutexes_fields_info;
schema->fill_table = i_s_innodb_mutexes_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_mutexes =
{
/* 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_MUTEXES"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB SYS_DATAFILES"),
/* 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_mutexes_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),
/* Maria extension */
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
};
/** SYS_SEMAPHORE_WAITS ************************************************/
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS */
static ST_FIELD_INFO innodb_sys_semaphore_waits_fields_info[] =
{
// SYS_SEMAPHORE_WAITS_THREAD_ID 0
{STRUCT_FLD(field_name, "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)},
// SYS_SEMAPHORE_WAITS_OBJECT_NAME 1
{STRUCT_FLD(field_name, "OBJECT_NAME"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_FILE 2
{STRUCT_FLD(field_name, "FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_LINE 3
{STRUCT_FLD(field_name, "LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_WAIT_TIME 4
{STRUCT_FLD(field_name, "WAIT_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)},
// SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5
{STRUCT_FLD(field_name, "WAIT_OBJECT"),
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)},
// SYS_SEMAPHORE_WAITS_WAIT_TYPE 6
{STRUCT_FLD(field_name, "WAIT_TYPE"),
STRUCT_FLD(field_length, 16),
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)},
// SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7
{STRUCT_FLD(field_name, "HOLDER_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)},
// SYS_SEMAPHORE_WAITS_HOLDER_FILE 8
{STRUCT_FLD(field_name, "HOLDER_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_HOLDER_LINE 9
{STRUCT_FLD(field_name, "HOLDER_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_CREATED_FILE 10
{STRUCT_FLD(field_name, "CREATED_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_CREATED_LINE 11
{STRUCT_FLD(field_name, "CREATED_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_WRITER_THREAD 12
{STRUCT_FLD(field_name, "WRITER_THREAD"),
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)},
// SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13
{STRUCT_FLD(field_name, "RESERVATION_MODE"),
STRUCT_FLD(field_length, 16),
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)},
// SYS_SEMAPHORE_WAITS_READERS 14
{STRUCT_FLD(field_name, "READERS"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15
{STRUCT_FLD(field_name, "WAITERS_FLAG"),
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)},
// SYS_SEMAPHORE_WAITS_LOCK_WORD 16
{STRUCT_FLD(field_name, "LOCK_WORD"),
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)},
// SYS_SEMAPHORE_WAITS_LAST_READER_FILE 17
{STRUCT_FLD(field_name, "LAST_READER_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_LAST_READER_LINE 18
{STRUCT_FLD(field_name, "LAST_READER_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 19
{STRUCT_FLD(field_name, "LAST_WRITER_FILE"),
STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
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)},
// SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 20
{STRUCT_FLD(field_name, "LAST_WRITER_LINE"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
// SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 21
{STRUCT_FLD(field_name, "OS_WAIT_COUNT"),
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
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
};
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS
@return 0 on success */
static
int
innodb_sys_semaphore_waits_init(
/*============================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_sys_semaphore_waits_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = innodb_sys_semaphore_waits_fields_info;
schema->fill_table = sync_arr_fill_sys_semphore_waits_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_semaphore_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_SYS_SEMAPHORE_WAITS"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, maria_plugin_author),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB SYS_SEMAPHORE_WAITS"),
/* 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_sys_semaphore_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),
/* Maria extension */
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
};

View file

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyrigth (c) 2014, 2015, MariaDB Corporation
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
@ -21,12 +22,14 @@ this program; if not, write to the Free Software Foundation, Inc.,
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
Modified Dec 29, 2014 Jan Lindström
*******************************************************/
#ifndef i_s_h
#define i_s_h
const char plugin_author[] = "Oracle Corporation";
const char maria_plugin_author[] = "MariaDB Corporation";
#define st_mysql_plugin st_maria_plugin
@ -60,7 +63,91 @@ extern struct st_mysql_plugin i_s_innodb_sys_foreign_cols;
extern struct st_mysql_plugin i_s_innodb_sys_tablespaces;
extern struct st_mysql_plugin i_s_innodb_sys_datafiles;
extern struct st_mysql_plugin i_s_innodb_changed_pages;
extern struct st_mysql_plugin i_s_innodb_mutexes;
extern struct st_maria_plugin i_s_innodb_tablespaces_encryption;
extern struct st_maria_plugin i_s_innodb_tablespaces_scrubbing;
extern struct st_mysql_plugin i_s_innodb_sys_semaphore_waits;
/** 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, Sql_condition::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 && !defined __clang__
#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)}
/** Fields on INFORMATION_SCHEMA.SYS_SEMAMPHORE_WAITS table */
#define SYS_SEMAPHORE_WAITS_THREAD_ID 0
#define SYS_SEMAPHORE_WAITS_OBJECT_NAME 1
#define SYS_SEMAPHORE_WAITS_FILE 2
#define SYS_SEMAPHORE_WAITS_LINE 3
#define SYS_SEMAPHORE_WAITS_WAIT_TIME 4
#define SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5
#define SYS_SEMAPHORE_WAITS_WAIT_TYPE 6
#define SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7
#define SYS_SEMAPHORE_WAITS_HOLDER_FILE 8
#define SYS_SEMAPHORE_WAITS_HOLDER_LINE 9
#define SYS_SEMAPHORE_WAITS_CREATED_FILE 10
#define SYS_SEMAPHORE_WAITS_CREATED_LINE 11
#define SYS_SEMAPHORE_WAITS_WRITER_THREAD 12
#define SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13
#define SYS_SEMAPHORE_WAITS_READERS 14
#define SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15
#define SYS_SEMAPHORE_WAITS_LOCK_WORD 16
#define SYS_SEMAPHORE_WAITS_LAST_READER_FILE 17
#define SYS_SEMAPHORE_WAITS_LAST_READER_LINE 18
#define SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 19
#define SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 20
#define SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 21
/*******************************************************************//**
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 */
int
field_store_ulint(
/*==============*/
Field* field, /*!< in/out: target field for storage */
ulint n); /*!< in: value to store */
/*******************************************************************//**
Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
@return 0 on success */
int
field_store_string(
/*===============*/
Field* field, /*!< in/out: target field for storage */
const char* str); /*!< in: NUL-terminated utf-8 string,
or NULL */
#endif /* i_s_h */

View file

@ -17,6 +17,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
*****************************************************************************/
#include "univ.i"
#include <mysqld_error.h>
#include <sql_acl.h> // PROCESS_ACL
@ -43,94 +44,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#define PLUGIN_AUTHOR "Percona Inc."
#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, Sql_condition::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 && !defined __clang__
#define STRUCT_FLD(name, value) name: value
#else
#define STRUCT_FLD(name, value) value
#endif
#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)}
/*******************************************************************//**
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);
}
/*******************************************************************//**
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);
}
static
int
i_s_common_deinit(

View file

@ -708,6 +708,9 @@ extern ulong srv_fatal_semaphore_wait_threshold;
/** Default encryption key used for page encryption */
extern uint srv_default_page_encryption_key;
/** Enable semaphore request instrumentation */
extern my_bool srv_instrument_semaphores;
# ifdef UNIV_PFS_THREAD
/* Keys to register InnoDB threads with performance schema */
extern mysql_pfs_key_t buf_page_cleaner_thread_key;

View file

@ -31,7 +31,7 @@ Created 9/5/1995 Heikki Tuuri
#include "ut0mem.h"
#include "os0thread.h"
/** Synchronization wait array cell */
/** Synchonization cell */
struct sync_cell_t;
/** Synchronization wait array */
struct sync_array_t;
@ -154,6 +154,16 @@ UNIV_INTERN
void
sync_array_print_xtradb(void);
/*****************************************************************//**
Gets the nth cell in array.
@return cell */
UNIV_INTERN
sync_cell_t*
sync_array_get_nth_cell(
/*====================*/
sync_array_t* arr, /*!< in: sync array */
ulint n); /*!< in: index */
#ifndef UNIV_NONINL
#include "sync0arr.ic"
#endif

View file

@ -40,6 +40,9 @@ Created 9/11/1995 Heikki Tuuri
#include "sync0sync.h"
#include "os0sync.h"
/** Enable semaphore request instrumentation */
extern my_bool srv_instrument_semaphores;
/* The following undef is to prevent a name conflict with a macro
in MySQL: */
#undef rw_lock_t
@ -153,14 +156,14 @@ defined, the rwlock are instrumented with performance schema probes. */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), (level), __FILE__, __LINE__, #L)
rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), __FILE__, __LINE__, #L)
rw_lock_create_func((L), #L, __FILE__, __LINE__)
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), #L)
rw_lock_create_func((L), __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
/**************************************************************//**
@ -218,14 +221,14 @@ unlocking, not the corresponding function. */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), (level), __FILE__, __LINE__, #L)
pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__, #L)
pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), #L)
pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
/******************************************************************
@ -295,10 +298,10 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
Creates, or rather, initializes a priority rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized
@ -313,10 +316,10 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
Calling this function is obligatory only if the memory buffer containing
the rw-lock is freed. Removes an rw-lock object from the global list. The
@ -752,8 +755,11 @@ struct rw_lock_t {
struct PSI_rwlock *pfs_psi;/*!< The instrumentation hook */
#endif
ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
//const char* cfile_name;/*!< File name where lock created */
const char* cfile_name;/*!< File name where lock created */
const char* lock_name;/*!< lock name */
os_thread_id_t thread_id;/*!< thread id */
const char* file_name;/*!< File name where the lock was obtained */
ulint line; /*!< Line where the rw-lock was locked */
/* last s-lock file/line is not guaranteed to be correct */
const char* last_s_file_name;/*!< File name where last s-locked */
const char* last_x_file_name;/*!< File name where last x-locked */
@ -764,7 +770,7 @@ struct rw_lock_t {
are at the start of this struct, thus we can
peek this field without causing much memory
bus traffic */
//unsigned cline:14; /*!< Line where created */
unsigned cline:14; /*!< Line where created */
unsigned last_s_line:14; /*!< Line number where last time s-locked */
unsigned last_x_line:14; /*!< Line number where last time x-locked */
#ifdef UNIV_DEBUG
@ -853,10 +859,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_create_func()
@ -873,10 +879,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_lock_func()

View file

@ -382,6 +382,12 @@ rw_lock_s_lock_low(
lock->last_s_file_name = file_name;
lock->last_s_line = line;
if (srv_instrument_semaphores) {
lock->thread_id = os_thread_get_curr_id();
lock->file_name = file_name;
lock->line = line;
}
return(TRUE); /* locking succeeded */
}
@ -551,6 +557,12 @@ rw_lock_x_lock_func_nowait(
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
#endif
if (srv_instrument_semaphores) {
lock->thread_id = os_thread_get_curr_id();
lock->file_name = file_name;
lock->line = line;
}
lock->last_x_file_name = file_name;
lock->last_x_line = line;
@ -799,10 +811,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
/* Initialize the rwlock for performance schema */
lock->pfs_psi = PSI_RWLOCK_CALL(init_rwlock)(key, lock);
@ -813,10 +825,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
cfile_name,
cline,
# endif /* UNIV_DEBUG */
cmutex_name);
cmutex_name,
cfile_name,
cline);
}
/******************************************************************//**
@ -834,10 +846,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
/* Initialize the rwlock for performance schema */
lock->base_lock.pfs_psi = PSI_RWLOCK_CALL(init_rwlock)(key, lock);
@ -848,10 +860,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
cfile_name,
cline,
# endif /* UNIV_DEBUG */
cmutex_name);
cmutex_name,
cfile_name,
cline);
}
/******************************************************************//**

View file

@ -43,6 +43,9 @@ Created 9/5/1995 Heikki Tuuri
#include "sync0arr.h"
#include "ut0counter.h"
/** Enable semaphore request instrumentation */
extern my_bool srv_instrument_semaphores;
#if defined(UNIV_DEBUG) && !defined(UNIV_HOTBACKUP)
extern "C" my_bool timed_mutexes;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
@ -189,7 +192,7 @@ necessary only if the memory block containing it is freed. */
# endif/* UNIV_SYNC_DEBUG */
# else
# define mutex_create(K, M, level) \
pfs_mutex_create_func((K), (M), #M)
pfs_mutex_create_func((K), (M), __FILE__, __LINE__, #M)
# endif /* UNIV_DEBUG */
# define mutex_enter(M) \
@ -256,9 +259,9 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
/******************************************************************//**
@ -275,11 +278,11 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where
created */
ulint cline, /*!< in: file line where
created */
#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
/******************************************************************//**
NOTE! Use the corresponding macro mutex_free(), not directly this function!
@ -402,9 +405,9 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
const char* cmutex_name);
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_create(), not directly
@ -423,11 +426,11 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where
created */
ulint cline, /*!< in: file line where
created */
# endif /* UNIV_DEBUG */
const char* cmutex_name);
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_enter(), not directly
@ -947,27 +950,28 @@ struct ib_mutex_t {
Otherwise, this is 0. */
UT_LIST_NODE_T(ib_mutex_t) list; /*!< All allocated mutexes are put into
a list. Pointers to the next and prev. */
#ifdef UNIV_SYNC_DEBUG
const char* file_name; /*!< File where the mutex was locked */
ulint line; /*!< Line where the mutex was locked */
ulint level; /*!< Level in the global latching order */
ulint level; /*!< Level in the global latching order */
#endif /* UNIV_SYNC_DEBUG */
#ifdef UNIV_DEBUG
const char* cfile_name;/*!< File name where mutex created */
ulint cline; /*!< Line where created */
#endif
const char* file_name; /*!< File where the mutex was locked */
ulint line; /*!< Line where the mutex was locked */
const char* cfile_name; /*!< File name where mutex created */
ulint cline; /*!< Line where created */
ulong count_os_wait; /*!< count of os_wait */
const char* cmutex_name; /*!< mutex name */
os_thread_id_t thread_id; /*!< The thread id of the thread
which locked the mutex. */
#ifdef UNIV_DEBUG
/** Value of mutex_t::magic_n */
# define MUTEX_MAGIC_N 979585UL
os_thread_id_t thread_id; /*!< The thread id of the thread
which locked the mutex. */
ulint magic_n; /*!< MUTEX_MAGIC_N */
ulint ib_mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
#endif /* UNIV_DEBUG */
const char* cmutex_name; /*!< mutex name */
#ifdef UNIV_PFS_MUTEX
struct PSI_mutex* pfs_psi; /*!< The performance schema
instrumentation hook */

View file

@ -165,7 +165,7 @@ mutex_exit_func(
{
ut_ad(mutex_own(mutex));
ut_d(mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED);
mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED;
#ifdef UNIV_SYNC_DEBUG
sync_thread_reset_level(mutex);
@ -205,7 +205,7 @@ mutex_exit_func(
{
ut_ad(mutex_own(mutex));
ut_d(mutex->base_mutex.thread_id = (os_thread_id_t) ULINT_UNDEFINED);
mutex->base_mutex.thread_id = (os_thread_id_t) ULINT_UNDEFINED;
#ifdef UNIV_SYNC_DEBUG
sync_thread_reset_level(&mutex->base_mutex);
@ -264,10 +264,15 @@ mutex_enter_func(
the atomic test_and_set; we could peek, and possibly save time. */
if (!ib_mutex_test_and_set(mutex)) {
ut_d(mutex->thread_id = os_thread_get_curr_id());
mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
if (srv_instrument_semaphores) {
mutex->file_name = file_name;
mutex->line = line;
}
return; /* Succeeded! */
}
@ -304,10 +309,15 @@ mutex_enter_func(
the atomic test_and_set; we could peek, and possibly save time. */
if (!ib_mutex_test_and_set(&mutex->base_mutex)) {
ut_d(mutex->base_mutex.thread_id = os_thread_get_curr_id());
mutex->base_mutex.thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(&mutex->base_mutex, file_name, line);
#endif
if(srv_instrument_semaphores) {
mutex->base_mutex.file_name = file_name;
mutex->base_mutex.line = line;
}
return; /* Succeeded! */
}
@ -515,9 +525,9 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
{
mutex->pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex);
@ -527,9 +537,9 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
cfile_name,
cline,
# endif /* UNIV_DEBUG */
cmutex_name);
}
@ -550,11 +560,11 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where
created */
ulint cline, /*!< in: file line where
created */
# endif /* UNIV_DEBUG */
const char* cmutex_name)
{
mutex->base_mutex.pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex);
@ -564,9 +574,9 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
cfile_name,
cline,
# endif /* UNIV_DEBUG */
cmutex_name);
}

View file

@ -78,6 +78,7 @@ Created 10/8/1995 Heikki Tuuri
#include "fil0pagecompress.h"
#include <my_rdtsc.h>
#include "btr0scrub.h"
#include "fil0pageencryption.h"
/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
ibool innobase_thd_is_idle(const void* thd);
@ -670,7 +671,10 @@ second. */
static time_t srv_last_log_flush_time;
/** Default encryption key used for page encryption */
UNIV_INTERN uint srv_default_page_encryption_key;
UNIV_INTERN uint srv_default_page_encryption_key = DEFAULT_ENCRYPTION_KEY;
/** Enable semaphore request instrumentation */
UNIV_INTERN my_bool srv_instrument_semaphores = FALSE;
/* Interval in seconds at which various tasks are performed by the
master thread when server is active. In order to balance the workload,

View file

@ -2,7 +2,7 @@
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, 2014, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -31,11 +31,26 @@ The wait array used in synchronization primitives
Created 9/5/1995 Heikki Tuuri
*******************************************************/
#include "univ.i"
#include "sync0arr.h"
#ifdef UNIV_NONINL
#include "sync0arr.ic"
#endif
#include <mysqld_error.h>
#include <mysql/plugin.h>
#include <hash.h>
#include <myisampack.h>
#include <sql_acl.h>
#include <mysys_err.h>
#include <my_sys.h>
#include "srv0srv.h"
#include "srv0start.h"
#include "i_s.h"
#include <sql_plugin.h>
#include <innodb_priv.h>
#include "sync0sync.h"
#include "sync0rw.h"
#include "os0sync.h"
@ -117,7 +132,6 @@ for an event allocated for the array without owning the
protecting mutex (depending on the case: OS or database mutex), but
all changes (set or reset) to the state of the event must be made
while owning the mutex. */
/** Synchronization array */
struct sync_array_t {
ulint n_reserved; /*!< number of currently reserved
@ -170,7 +184,6 @@ sync_array_detect_deadlock(
/*****************************************************************//**
Gets the nth cell in array.
@return cell */
static
sync_cell_t*
sync_array_get_nth_cell(
/*====================*/
@ -1374,3 +1387,173 @@ sync_array_print_xtradb(void)
fputs("InnoDB: Semaphore wait debug output ended:\n", stderr);
}
/**********************************************************************//**
Get number of items on sync array. */
UNIV_INTERN
ulint
sync_arr_get_n_items(void)
/*======================*/
{
sync_array_t* sync_arr = sync_array_get();
return (ulint) sync_arr->n_cells;
}
/******************************************************************//**
Get specified item from sync array if it is reserved. Set given
pointer to array item if it is reserved.
@return true if item is reserved, false othervise */
UNIV_INTERN
ibool
sync_arr_get_item(
/*==============*/
ulint i, /*!< in: requested item */
sync_cell_t **cell) /*!< out: cell contents if item
reserved */
{
sync_array_t* sync_arr;
sync_cell_t* wait_cell;
void* wait_object;
ibool found = FALSE;
sync_arr = sync_array_get();
wait_cell = sync_array_get_nth_cell(sync_arr, i);
if (wait_cell) {
wait_object = wait_cell->wait_object;
if(wait_object != NULL && wait_cell->waiting) {
found = TRUE;
*cell = wait_cell;
}
}
return found;
}
/*******************************************************************//**
Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
Loop through each item on sync array, and extract the column
information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
@return 0 on success */
UNIV_INTERN
int
sync_arr_fill_sys_semphore_waits_table(
/*===================================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (not used) */
{
Field** fields;
ulint n_items;
DBUG_ENTER("i_s_sys_semaphore_waits_fill_table");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* deny access to user without PROCESS_ACL privilege */
if (check_global_access(thd, PROCESS_ACL)) {
DBUG_RETURN(0);
}
fields = tables->table->field;
n_items = sync_arr_get_n_items();
ulint type;
for(ulint i=0; i < n_items;i++) {
sync_cell_t *cell=NULL;
if (sync_arr_get_item(i, &cell)) {
ib_prio_mutex_t* prio_mutex;
ib_mutex_t* mutex;
type = cell->request_type;
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_THREAD_ID], (longlong)os_thread_pf(cell->thread)));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_FILE], innobase_basename(cell->file)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LINE], cell->line));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_TIME], (longlong)difftime(time(NULL), cell->reservation_time)));
if (type == SYNC_MUTEX || type == SYNC_PRIO_MUTEX) {
if (type == SYNC_MUTEX) {
mutex = static_cast<ib_mutex_t*>(cell->old_wait_mutex);
} else {
prio_mutex = static_cast<ib_prio_mutex_t*>
(cell->old_wait_mutex);
mutex = &prio_mutex->base_mutex;
}
if (mutex) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], mutex->cmutex_name));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT], (longlong)mutex));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "MUTEX"));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID], (longlong)mutex->thread_id));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(mutex->file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE], mutex->line));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_CREATED_FILE], innobase_basename(mutex->cfile_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_CREATED_LINE], mutex->cline));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG], (longlong)mutex->waiters));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD], (longlong)mutex->lock_word));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(mutex->file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE], mutex->line));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT], mutex->count_os_wait));
}
} else if (type == RW_LOCK_EX
|| type == RW_LOCK_WAIT_EX
|| type == RW_LOCK_SHARED
|| type == PRIO_RW_LOCK_SHARED
|| type == PRIO_RW_LOCK_EX) {
rw_lock_t* rwlock=NULL;
prio_rw_lock_t* prio_rwlock=NULL;
if (type == RW_LOCK_EX || type == RW_LOCK_WAIT_EX
|| type == RW_LOCK_SHARED) {
rwlock = static_cast<rw_lock_t *>
(cell->old_wait_rw_lock);
} else {
prio_rwlock = static_cast<prio_rw_lock_t *>
(cell->old_wait_rw_lock);
rwlock = &prio_rwlock->base_lock;
}
if (rwlock) {
ulint writer = rw_lock_get_writer(rwlock);
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT], (longlong)rwlock));
if (type == RW_LOCK_EX) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_EX"));
} else if (type == RW_LOCK_WAIT_EX) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_WAIT_EX"));
} else if (type == RW_LOCK_SHARED) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_SHARED"));
}
if (writer != RW_LOCK_NOT_LOCKED) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], rwlock->lock_name));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WRITER_THREAD], (longlong)os_thread_pf(rwlock->writer_thread)));
if (writer == RW_LOCK_EX) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_RESERVATION_MODE], "RW_LOCK_EX"));
} else if (writer == RW_LOCK_WAIT_EX) {
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_RESERVATION_MODE], "RW_LOCK_WAIT_EX"));
}
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID], (longlong)rwlock->thread_id));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(rwlock->file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE], rwlock->line));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_READERS], rw_lock_get_reader_count(rwlock)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG], (longlong)rwlock->waiters));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD], (longlong)rwlock->lock_word));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_READER_FILE], innobase_basename(rwlock->last_s_file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_READER_LINE], rwlock->last_s_line));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(rwlock->last_x_file_name)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE], rwlock->last_x_line));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT], rwlock->count_os_wait));
}
}
}
OK(schema_table_store_record(thd, tables->table));
}
}
DBUG_RETURN(0);
}

View file

@ -209,10 +209,10 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
/* If this is the very first time a synchronization object is
created, then the following call initializes the sync system. */
@ -221,15 +221,14 @@ rw_lock_create_func(
mutex_create(rw_lock_mutex_key, rw_lock_get_mutex(lock),
SYNC_NO_ORDER_CHECK);
ut_d(lock->mutex.cfile_name = cfile_name);
ut_d(lock->mutex.cline = cline);
lock->mutex.cmutex_name = cmutex_name;
lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline;
lock->mutex.lock_name = cmutex_name;
ut_d(lock->mutex.ib_mutex_type = 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
# ifdef UNIV_DEBUG
UT_NOT_USED(cfile_name);
UT_NOT_USED(cline);
UT_NOT_USED(cmutex_name);
# endif
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
@ -252,9 +251,12 @@ rw_lock_create_func(
ut_d(lock->magic_n = RW_LOCK_MAGIC_N);
lock->cfile_name = cfile_name;
lock->cline = (unsigned int) cline;
lock->lock_name = cmutex_name;
lock->count_os_wait = 0;
lock->file_name = "not yet reserved";
lock->line = 0;
lock->last_s_file_name = "not yet reserved";
lock->last_x_file_name = "not yet reserved";
lock->last_s_line = 0;
@ -286,20 +288,21 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
rw_lock_create_func(&lock->base_lock,
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
level,
# endif
cfile_name,
cline,
#endif
cmutex_name);
cmutex_name,
cfile_name,
cline);
lock->high_priority_s_waiters = 0;
lock->high_priority_s_event = os_event_create();
lock->high_priority_x_waiters = 0;
@ -655,6 +658,12 @@ rw_lock_x_lock_wait(
file_name, line);
#endif
if (srv_instrument_semaphores) {
lock->thread_id = os_thread_get_curr_id();
lock->file_name = file_name;
lock->line = line;
}
sync_array_wait_event(sync_arr, index);
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(
@ -740,6 +749,12 @@ rw_lock_x_lock_low(
lock->last_x_file_name = file_name;
lock->last_x_line = (unsigned int) line;
if (srv_instrument_semaphores) {
lock->thread_id = os_thread_get_curr_id();
lock->file_name = file_name;
lock->line = line;
}
return(TRUE);
}

View file

@ -273,9 +273,9 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
{
#if defined(HAVE_ATOMIC_BUILTINS)
@ -288,16 +288,13 @@ mutex_create_func(
mutex_set_waiters(mutex, 0);
#ifdef UNIV_DEBUG
mutex->magic_n = MUTEX_MAGIC_N;
mutex->level = level;
#endif /* UNIV_DEBUG */
#ifdef UNIV_SYNC_DEBUG
mutex->line = 0;
mutex->file_name = "not yet reserved";
mutex->level = level;
#endif /* UNIV_SYNC_DEBUG */
#ifdef UNIV_DEBUG
mutex->cfile_name = cfile_name;
mutex->cline = cline;
#endif /* UNIV_DEBUG */
mutex->count_os_wait = 0;
mutex->cmutex_name= cmutex_name;
@ -339,11 +336,11 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where
created */
ulint cline, /*!< in: file line where
created */
#endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
{
mutex_create_func(&mutex->base_mutex,
@ -351,9 +348,9 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
#endif /* UNIV_SYNC_DEBUG */
#endif /* UNIV_DEBUG */
cfile_name,
cline,
#endif /* UNIV_DEBUG */
cmutex_name);
mutex->high_priority_waiters = 0;
mutex->high_priority_event = os_event_create();
@ -463,10 +460,14 @@ mutex_enter_nowait_func(
if (!ib_mutex_test_and_set(mutex)) {
ut_d(mutex->thread_id = os_thread_get_curr_id());
mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
if (srv_instrument_semaphores) {
mutex->file_name = file_name;
mutex->line = line;
}
return(0); /* Succeeded! */
}
@ -607,10 +608,15 @@ spin_loop:
if (ib_mutex_test_and_set(mutex) == 0) {
/* Succeeded! */
ut_d(mutex->thread_id = os_thread_get_curr_id());
mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
if (srv_instrument_semaphores) {
mutex->file_name = file_name;
mutex->line = line;
}
return;
}
@ -661,10 +667,14 @@ spin_loop:
sync_array_free_cell(sync_arr, index);
ut_d(mutex->thread_id = os_thread_get_curr_id());
mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
if (srv_instrument_semaphores) {
mutex->file_name = file_name;
mutex->line = line;
}
if (prio_mutex) {
os_atomic_decrement_ulint(