diff options
author | Jan Lindström <jan.lindstrom@skysql.com> | 2015-02-21 21:45:16 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@skysql.com> | 2015-02-21 21:45:16 +0200 |
commit | 1cc7befc14cd2ad637ffb6fc29fae0f978735acf (patch) | |
tree | 8221773550b173d5b1d41243605b1f5ad72fe7f3 | |
parent | 9152b83973419ea034bb6040703c18b3ee87e084 (diff) | |
download | mariadb-git-1cc7befc14cd2ad637ffb6fc29fae0f978735acf.tar.gz |
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.
39 files changed, 2173 insertions, 293 deletions
diff --git a/mysql-test/r/information_schema_all_engines.result b/mysql-test/r/information_schema_all_engines.result index 731fabf57f5..7f79dd883e2 100644 --- a/mysql-test/r/information_schema_all_engines.result +++ b/mysql-test/r/information_schema_all_engines.result @@ -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 diff --git a/mysql-test/suite/innodb/r/innodb_mutexes.result b/mysql-test/suite/innodb/r/innodb_mutexes.result new file mode 100644 index 00000000000..129d7f0762b --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_mutexes.result @@ -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; diff --git a/mysql-test/suite/innodb/r/innodb_sys_semaphore_waits.result b/mysql-test/suite/innodb/r/innodb_sys_semaphore_waits.result new file mode 100644 index 00000000000..4164e043b2c --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_sys_semaphore_waits.result @@ -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 diff --git a/mysql-test/suite/innodb/t/innodb_mutexes-master.opt b/mysql-test/suite/innodb/t/innodb_mutexes-master.opt new file mode 100644 index 00000000000..493faf1903e --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_mutexes-master.opt @@ -0,0 +1 @@ +--innodb-mutexes
\ No newline at end of file diff --git a/mysql-test/suite/innodb/t/innodb_mutexes.test b/mysql-test/suite/innodb/t/innodb_mutexes.test new file mode 100644 index 00000000000..3b6b949c25d --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_mutexes.test @@ -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;
\ No newline at end of file diff --git a/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits-master.opt b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits-master.opt new file mode 100644 index 00000000000..22272485540 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits-master.opt @@ -0,0 +1,3 @@ +--innodb-fatal-semaphore-wait-threshold=1 +--innodb-sys-semaphore-waits=1 +--innodb-instrument-semaphores=1 diff --git a/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test new file mode 100644 index 00000000000..eda798e4e12 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test @@ -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 diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index 840da8405c3..0ace47d1378 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -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; diff --git a/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores.result b/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores.result new file mode 100644 index 00000000000..dc8fba41e0b --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores.result @@ -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 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index b3e974a75f6..030b8cd367c 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -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 diff --git a/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test b/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test new file mode 100644 index 00000000000..9b302be79b5 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test @@ -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 diff --git a/mysql-test/t/information_schema_all_engines-master.opt b/mysql-test/t/information_schema_all_engines-master.opt index dec3b51813f..43411c5033a 100644 --- a/mysql-test/t/information_schema_all_engines-master.opt +++ b/mysql-test/t/information_schema_all_engines-master.opt @@ -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 diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a8cece74666..bd81ae2bb26 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -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; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index f0202e232b7..3664c05e69e 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -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), +}; diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h index 4b248b0673a..296f64ddd74 100644 --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -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 */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index a23e9306716..31db78ae5ee 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -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; diff --git a/storage/innobase/include/sync0arr.h b/storage/innobase/include/sync0arr.h index 0e735192024..6c3225b1826 100644 --- a/storage/innobase/include/sync0arr.h +++ b/storage/innobase/include/sync0arr.h @@ -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 diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h index b36e04f2810..cfd9776959f 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -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 */ diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index bb05ae7daf1..afd25f3a071 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -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); } diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index f26e66f1a87..2ffa14fd7fb 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -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 diff --git a/storage/innobase/include/sync0sync.ic b/storage/innobase/include/sync0sync.ic index a5887b1fd6f..d29932b39a6 100644 --- a/storage/innobase/include/sync0sync.ic +++ b/storage/innobase/include/sync0sync.ic @@ -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 */ diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 07d8539836a..77b5e218723 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -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, diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc index 10c201e990e..e501423f222 100644 --- a/storage/innobase/sync/sync0arr.cc +++ b/storage/innobase/sync/sync0arr.cc @@ -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); +} diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc index 4ff330791a0..8e5faed08dd 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -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; diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index aa2b5fa29db..5f5c6d2a5f2 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -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; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index ee62dbc2d6a..e764d44c748 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -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; diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index 99b1f486862..79870c755f6 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/handler/i_s.cc @@ -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), +}; diff --git a/storage/xtradb/handler/i_s.h b/storage/xtradb/handler/i_s.h index f141af40c87..ee2442a22f2 100644 --- a/storage/xtradb/handler/i_s.h +++ b/storage/xtradb/handler/i_s.h @@ -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 */ diff --git a/storage/xtradb/handler/xtradb_i_s.cc b/storage/xtradb/handler/xtradb_i_s.cc index 7078ab752c2..96e31b94470 100644 --- a/storage/xtradb/handler/xtradb_i_s.cc +++ b/storage/xtradb/handler/xtradb_i_s.cc @@ -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( diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index de994e79b30..de33f767021 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -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; diff --git a/storage/xtradb/include/sync0arr.h b/storage/xtradb/include/sync0arr.h index 46e192d05f1..a3a326a0d1d 100644 --- a/storage/xtradb/include/sync0arr.h +++ b/storage/xtradb/include/sync0arr.h @@ -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 diff --git a/storage/xtradb/include/sync0rw.h b/storage/xtradb/include/sync0rw.h index 0ac6b0f3f69..1df6a793637 100644 --- a/storage/xtradb/include/sync0rw.h +++ b/storage/xtradb/include/sync0rw.h @@ -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() diff --git a/storage/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic index 8aadc406132..72bce228170 100644 --- a/storage/xtradb/include/sync0rw.ic +++ b/storage/xtradb/include/sync0rw.ic @@ -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); } /******************************************************************//** diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h index 72cfbf61dd8..8112fff8a30 100644 --- a/storage/xtradb/include/sync0sync.h +++ b/storage/xtradb/include/sync0sync.h @@ -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 */ diff --git a/storage/xtradb/include/sync0sync.ic b/storage/xtradb/include/sync0sync.ic index 8176ae55fd8..90789339249 100644 --- a/storage/xtradb/include/sync0sync.ic +++ b/storage/xtradb/include/sync0sync.ic @@ -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); } diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index f3d71fac155..37adca6975b 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -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, diff --git a/storage/xtradb/sync/sync0arr.cc b/storage/xtradb/sync/sync0arr.cc index 1701c705c5b..ebabc3d674e 100644 --- a/storage/xtradb/sync/sync0arr.cc +++ b/storage/xtradb/sync/sync0arr.cc @@ -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); +} diff --git a/storage/xtradb/sync/sync0rw.cc b/storage/xtradb/sync/sync0rw.cc index 3296e2e74a7..eac085513dc 100644 --- a/storage/xtradb/sync/sync0rw.cc +++ b/storage/xtradb/sync/sync0rw.cc @@ -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); } diff --git a/storage/xtradb/sync/sync0sync.cc b/storage/xtradb/sync/sync0sync.cc index 5732e1075cf..2bdaaa35a0e 100644 --- a/storage/xtradb/sync/sync0sync.cc +++ b/storage/xtradb/sync/sync0sync.cc @@ -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( |