logging_ok:

  Logging to logging@openlogging.org accepted
sql_yacc.yy, sql_parse.cc, sql_lex.h, lex.h:
  Implements the SHOW MUTEX STATUS command
set_var.cc, mysqld.cc, mysql_priv.h:
  Added new GLOBAL variable timed_mutexes
ha_innodb.h:
  New function innodb_mutex_show_status
ha_innodb.cc:
  Added new innodb variables in SHOW STATUS
  Implements the SHOW MUTEX STATUS command
innodb.test, innodb.result:
  Added new row_lock_waits status variables tests.
variables.test, variables.result:
  test new variable timed_mutexes
ut0ut.c:
  New function ut_usectime.
sync0sync.c:
  Mutex counting.
sync0rw.c:
  New mutex parameters initialization.
srv0srv.c:
  Counting row lock waits
row0sel.c, row0mysql.c:
  Setting row_lock or table_lock state to thd.
que0que.c:
  Added default no_lock_state to thd.
univ.i:
  Added UNIV_SRV_PRINT_LATCH_WAITS debug define
sync0sync.ic:
  Count mutex using.
sync0sync.h:
  Added new parameters to mutex structure for counting.
sync0rw.h:
  Added new parameters to rw_create_func.
srv0srv.h:
  Added new innodb varuables to SHOW STATUS.
que0que.h:
  Added thread lock states.
parent 4ba850ca
...@@ -230,6 +230,7 @@ ulli@morbus.(none) ...@@ -230,6 +230,7 @@ ulli@morbus.(none)
venu@hundin.mysql.fi venu@hundin.mysql.fi
venu@myvenu.com venu@myvenu.com
venu@work.mysql.com venu@work.mysql.com
vtkachenko@intelp4d.mysql.com
vva@eagle.mysql.r18.ru vva@eagle.mysql.r18.ru
vva@genie.(none) vva@genie.(none)
vva@mysql.r18.ru vva@mysql.r18.ru
......
...@@ -359,6 +359,7 @@ struct que_thr_struct{ ...@@ -359,6 +359,7 @@ struct que_thr_struct{
the control came */ the control came */
ulint resource; /* resource usage of the query thread ulint resource; /* resource usage of the query thread
thus far */ thus far */
ulint lock_state; /* lock state of thread (table or row) */
}; };
#define QUE_THR_MAGIC_N 8476583 #define QUE_THR_MAGIC_N 8476583
...@@ -482,6 +483,11 @@ struct que_fork_struct{ ...@@ -482,6 +483,11 @@ struct que_fork_struct{
#define QUE_THR_SUSPENDED 7 #define QUE_THR_SUSPENDED 7
#define QUE_THR_ERROR 8 #define QUE_THR_ERROR 8
/* Query thread lock states */
#define QUE_THR_LOCK_NOLOCK 0
#define QUE_THR_LOCK_ROW 1
#define QUE_THR_LOCK_TABLE 2
/* From where the cursor position is counted */ /* From where the cursor position is counted */
#define QUE_CUR_NOT_DEFINED 1 #define QUE_CUR_NOT_DEFINED 1
#define QUE_CUR_START 2 #define QUE_CUR_START 2
......
...@@ -525,6 +525,11 @@ struct export_var_struct{ ...@@ -525,6 +525,11 @@ struct export_var_struct{
ulint innodb_pages_created; ulint innodb_pages_created;
ulint innodb_pages_read; ulint innodb_pages_read;
ulint innodb_pages_written; ulint innodb_pages_written;
ulint innodb_row_lock_waits;
ulint innodb_row_lock_current_waits;
ib_longlong innodb_row_lock_time;
ulint innodb_row_lock_time_avg;
ulint innodb_row_lock_time_max;
ulint innodb_rows_read; ulint innodb_rows_read;
ulint innodb_rows_inserted; ulint innodb_rows_inserted;
ulint innodb_rows_updated; ulint innodb_rows_updated;
......
...@@ -61,8 +61,9 @@ Creates, or rather, initializes an rw-lock object in a specified memory ...@@ -61,8 +61,9 @@ Creates, or rather, initializes an rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized location (which must be appropriately aligned). The rw-lock is initialized
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
is necessary only if the memory block containing it is freed. */ is necessary only if the memory block containing it is freed. */
#define rw_lock_create(L) rw_lock_create_func(\
#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__) (L), __FILE__, __LINE__, __STRING(L))
/*=====================*/ /*=====================*/
/********************************************************************** /**********************************************************************
Creates, or rather, initializes an rw-lock object in a specified memory Creates, or rather, initializes an rw-lock object in a specified memory
...@@ -75,7 +76,8 @@ rw_lock_create_func( ...@@ -75,7 +76,8 @@ rw_lock_create_func(
/*================*/ /*================*/
rw_lock_t* lock, /* in: pointer to memory */ rw_lock_t* lock, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */ const char* cfile_name, /* in: file name where created */
ulint cline); /* in: file line where created */ ulint cline, /* in: file line where created */
const char* cmutex_name); /* in: mutex name */
/********************************************************************** /**********************************************************************
Calling this function is obligatory only if the memory buffer containing 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 the rw-lock is freed. Removes an rw-lock object from the global list. The
......
...@@ -17,6 +17,8 @@ Created 9/5/1995 Heikki Tuuri ...@@ -17,6 +17,8 @@ Created 9/5/1995 Heikki Tuuri
#include "os0sync.h" #include "os0sync.h"
#include "sync0arr.h" #include "sync0arr.h"
extern my_bool timed_mutexes;
/********************************************************************** /**********************************************************************
Initializes the synchronization data structures. */ Initializes the synchronization data structures. */
...@@ -35,8 +37,7 @@ location (which must be appropriately aligned). The mutex is initialized ...@@ -35,8 +37,7 @@ location (which must be appropriately aligned). The mutex is initialized
in the reset state. Explicit freeing of the mutex with mutex_free is in the reset state. Explicit freeing of the mutex with mutex_free is
necessary only if the memory block containing it is freed. */ necessary only if the memory block containing it is freed. */
#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__, __STRING(M))
#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__)
/*===================*/ /*===================*/
/********************************************************************** /**********************************************************************
Creates, or rather, initializes a mutex object in a specified memory Creates, or rather, initializes a mutex object in a specified memory
...@@ -49,7 +50,8 @@ mutex_create_func( ...@@ -49,7 +50,8 @@ mutex_create_func(
/*==============*/ /*==============*/
mutex_t* mutex, /* in: pointer to memory */ mutex_t* mutex, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */ const char* cfile_name, /* in: file name where created */
ulint cline); /* in: file line where created */ ulint cline, /* in: file line where created */
const char* cmutex_name); /* in: mutex name */
/********************************************************************** /**********************************************************************
Calling this function is obligatory only if the memory buffer containing Calling this function is obligatory only if the memory buffer containing
the mutex is freed. Removes a mutex object from the mutex list. The mutex the mutex is freed. Removes a mutex object from the mutex list. The mutex
...@@ -471,6 +473,15 @@ struct mutex_struct { ...@@ -471,6 +473,15 @@ struct mutex_struct {
const char* cfile_name;/* File name where mutex created */ const char* cfile_name;/* File name where mutex created */
ulint cline; /* Line where created */ ulint cline; /* Line where created */
ulint magic_n; ulint magic_n;
ulong count_using; /* count of times mutex used */
ulong count_spin_loop; /* count of spin loops */
ulong count_spin_rounds; /* count of spin rounds */
ulong count_os_wait; /* count of os_wait */
ulong count_os_yield; /* count of os_wait */
ulonglong lspent_time; /* mutex os_wait timer msec */
ulonglong lmax_spent_time; /* mutex os_wait timer msec */
const char* cmutex_name;/* mutex name */
ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */
}; };
#define MUTEX_MAGIC_N (ulint)979585 #define MUTEX_MAGIC_N (ulint)979585
...@@ -504,6 +515,13 @@ extern ibool sync_order_checks_on; ...@@ -504,6 +515,13 @@ extern ibool sync_order_checks_on;
/* This variable is set to TRUE when sync_init is called */ /* This variable is set to TRUE when sync_init is called */
extern ibool sync_initialized; extern ibool sync_initialized;
/* Global list of database mutexes (not OS mutexes) created. */
UT_LIST_BASE_NODE_T(mutex_t) mutex_list;
/* Mutex protecting the mutex_list variable */
mutex_t mutex_list_mutex;
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "sync0sync.ic" #include "sync0sync.ic"
#endif #endif
......
...@@ -249,8 +249,11 @@ mutex_enter_func( ...@@ -249,8 +249,11 @@ mutex_enter_func(
/* Note that we do not peek at the value of lock_word before trying /* Note that we do not peek at the value of lock_word before trying
the atomic test_and_set; we could peek, and possibly save time. */ the atomic test_and_set; we could peek, and possibly save time. */
mutex->count_using++;
if (!mutex_test_and_set(mutex)) { if (!mutex_test_and_set(mutex))
{
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line); mutex_set_debug_info(mutex, file_name, line);
#endif #endif
...@@ -258,4 +261,5 @@ mutex_enter_func( ...@@ -258,4 +261,5 @@ mutex_enter_func(
} }
mutex_spin_wait(mutex, file_name, line); mutex_spin_wait(mutex, file_name, line);
} }
...@@ -88,6 +88,7 @@ memory is read outside the allocated blocks. */ ...@@ -88,6 +88,7 @@ memory is read outside the allocated blocks. */
#define UNIV_SEARCH_DEBUG #define UNIV_SEARCH_DEBUG
#define UNIV_SYNC_PERF_STAT #define UNIV_SYNC_PERF_STAT
#define UNIV_SEARCH_PERF_STAT #define UNIV_SEARCH_PERF_STAT
#define UNIV_SRV_PRINT_LATCH_WAITS;
*/ */
#define UNIV_LIGHT_MEM_DEBUG #define UNIV_LIGHT_MEM_DEBUG
......
...@@ -163,6 +163,7 @@ que_thr_create( ...@@ -163,6 +163,7 @@ que_thr_create(
thr->run_node = NULL; thr->run_node = NULL;
thr->resource = 0; thr->resource = 0;
thr->lock_state = QUE_THR_LOCK_NOLOCK;
UT_LIST_ADD_LAST(thrs, parent->thrs, thr); UT_LIST_ADD_LAST(thrs, parent->thrs, thr);
......
...@@ -937,9 +937,10 @@ row_insert_for_mysql( ...@@ -937,9 +937,10 @@ row_insert_for_mysql(
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
que_thr_stop_for_mysql(thr); que_thr_stop_for_mysql(thr);
thr->lock_state= QUE_THR_LOCK_ROW;
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
&savept); &savept);
thr->lock_state= QUE_THR_LOCK_NOLOCK;
if (was_lock_wait) { if (was_lock_wait) {
goto run_again; goto run_again;
} }
...@@ -1171,9 +1172,11 @@ row_update_for_mysql( ...@@ -1171,9 +1172,11 @@ row_update_for_mysql(
return((int) err); return((int) err);
} }
thr->lock_state= QUE_THR_LOCK_ROW;
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
&savept); &savept);
thr->lock_state= QUE_THR_LOCK_NOLOCK;;
if (was_lock_wait) { if (was_lock_wait) {
goto run_again; goto run_again;
} }
......
...@@ -3791,8 +3791,10 @@ row_search_for_mysql( ...@@ -3791,8 +3791,10 @@ row_search_for_mysql(
que_thr_stop_for_mysql(thr); que_thr_stop_for_mysql(thr);
thr->lock_state= QUE_THR_LOCK_ROW;
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
thr->lock_state= QUE_THR_LOCK_NOLOCK;
if (was_lock_wait) { if (was_lock_wait) {
mtr_start(&mtr); mtr_start(&mtr);
......
...@@ -346,6 +346,12 @@ static ulint srv_n_rows_updated_old = 0; ...@@ -346,6 +346,12 @@ static ulint srv_n_rows_updated_old = 0;
static ulint srv_n_rows_deleted_old = 0; static ulint srv_n_rows_deleted_old = 0;
static ulint srv_n_rows_read_old = 0; static ulint srv_n_rows_read_old = 0;
ulint srv_n_lock_wait_count= 0;
ulint srv_n_lock_wait_current_count= 0;
ib_longlong srv_n_lock_wait_time= 0;
ulint srv_n_lock_max_wait_time= 0;
/* /*
Set the following to 0 if you want InnoDB to write messages on Set the following to 0 if you want InnoDB to write messages on
stderr on startup/shutdown stderr on startup/shutdown
...@@ -1378,7 +1384,11 @@ srv_suspend_mysql_thread( ...@@ -1378,7 +1384,11 @@ srv_suspend_mysql_thread(
trx_t* trx; trx_t* trx;
ibool had_dict_lock = FALSE; ibool had_dict_lock = FALSE;
ibool was_declared_inside_innodb = FALSE; ibool was_declared_inside_innodb = FALSE;
ib_longlong start_time, finish_time;
ulint diff_time;
ulint sec;
ulint ms;
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex)); ut_ad(!mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
...@@ -1420,7 +1430,15 @@ srv_suspend_mysql_thread( ...@@ -1420,7 +1430,15 @@ srv_suspend_mysql_thread(
os_event_reset(event); os_event_reset(event);
slot->suspend_time = ut_time(); slot->suspend_time = ut_time();
if (thr->lock_state == QUE_THR_LOCK_ROW)
{
srv_n_lock_wait_count++;
srv_n_lock_wait_current_count++;
ut_usectime(&sec, &ms);
start_time= (ib_longlong)sec * 1000000 + ms;
}
/* Wake the lock timeout monitor thread, if it is suspended */ /* Wake the lock timeout monitor thread, if it is suspended */
os_event_set(srv_lock_timeout_thread_event); os_event_set(srv_lock_timeout_thread_event);
...@@ -1471,7 +1489,22 @@ srv_suspend_mysql_thread( ...@@ -1471,7 +1489,22 @@ srv_suspend_mysql_thread(
slot->in_use = FALSE; slot->in_use = FALSE;
wait_time = ut_difftime(ut_time(), slot->suspend_time); wait_time = ut_difftime(ut_time(), slot->suspend_time);
if (thr->lock_state == QUE_THR_LOCK_ROW)
{
ut_usectime(&sec, &ms);
finish_time= (ib_longlong)sec * 1000000 + ms;
diff_time= finish_time-start_time;
srv_n_lock_wait_current_count--;
srv_n_lock_wait_time= srv_n_lock_wait_time + diff_time;
if (diff_time > srv_n_lock_max_wait_time)
{
srv_n_lock_max_wait_time= diff_time;
}
}
if (trx->was_chosen_as_deadlock_victim) { if (trx->was_chosen_as_deadlock_victim) {
trx->error_state = DB_DEADLOCK; trx->error_state = DB_DEADLOCK;
...@@ -1689,15 +1722,14 @@ srv_printf_innodb_monitor( ...@@ -1689,15 +1722,14 @@ srv_printf_innodb_monitor(
(srv_n_rows_read - srv_n_rows_read_old) (srv_n_rows_read - srv_n_rows_read_old)
/ time_elapsed); / time_elapsed);
srv_n_rows_inserted_old = srv_n_rows_inserted; srv_n_rows_inserted_old = srv_n_rows_inserted;
srv_n_rows_updated_old = srv_n_rows_updated; srv_n_rows_updated_old = srv_n_rows_updated;
srv_n_rows_deleted_old = srv_n_rows_deleted; srv_n_rows_deleted_old = srv_n_rows_deleted;
srv_n_rows_read_old = srv_n_rows_read; srv_n_rows_read_old = srv_n_rows_read;
fputs("----------------------------\n" fputs("----------------------------\n"
"END OF INNODB MONITOR OUTPUT\n" "END OF INNODB MONITOR OUTPUT\n"
"============================\n", file); "============================\n", file);
mutex_exit(&srv_innodb_monitor_mutex); mutex_exit(&srv_innodb_monitor_mutex);
fflush(file); fflush(file);
} }
...@@ -1746,11 +1778,19 @@ srv_export_innodb_status(void) ...@@ -1746,11 +1778,19 @@ srv_export_innodb_status(void)
export_vars.innodb_pages_created= buf_pool->n_pages_created; export_vars.innodb_pages_created= buf_pool->n_pages_created;
export_vars.innodb_pages_read= buf_pool->n_pages_read; export_vars.innodb_pages_read= buf_pool->n_pages_read;
export_vars.innodb_pages_written= buf_pool->n_pages_written; export_vars.innodb_pages_written= buf_pool->n_pages_written;
export_vars.innodb_row_lock_waits= srv_n_lock_wait_count;
export_vars.innodb_row_lock_current_waits= srv_n_lock_wait_current_count;
export_vars.innodb_row_lock_time= srv_n_lock_wait_time / 10000;
export_vars.innodb_row_lock_time_avg=
(srv_n_lock_wait_count > 0) ?
(srv_n_lock_wait_time / 10000 / srv_n_lock_wait_count) : 0;
export_vars.innodb_row_lock_time_max= srv_n_lock_max_wait_time / 10000;
export_vars.innodb_rows_read= srv_n_rows_read; export_vars.innodb_rows_read= srv_n_rows_read;
export_vars.innodb_rows_inserted= srv_n_rows_inserted; export_vars.innodb_rows_inserted= srv_n_rows_inserted;
export_vars.innodb_rows_updated= srv_n_rows_updated; export_vars.innodb_rows_updated= srv_n_rows_updated;
export_vars.innodb_rows_deleted= srv_n_rows_deleted; export_vars.innodb_rows_deleted= srv_n_rows_deleted;
mutex_exit(&srv_innodb_monitor_mutex); mutex_exit(&srv_innodb_monitor_mutex);
} }
/************************************************************************* /*************************************************************************
......
...@@ -90,7 +90,8 @@ rw_lock_create_func( ...@@ -90,7 +90,8 @@ rw_lock_create_func(
/*================*/ /*================*/
rw_lock_t* lock, /* in: pointer to memory */ rw_lock_t* lock, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */ const char* cfile_name, /* in: file name where created */
ulint cline) /* in: file line where created */ ulint cline, /* in: file line where created */
const char* cmutex_name) /* in: mutex name */
{ {
/* If this is the very first time a synchronization /* If this is the very first time a synchronization
object is created, then the following call initializes object is created, then the following call initializes
...@@ -101,7 +102,9 @@ rw_lock_create_func( ...@@ -101,7 +102,9 @@ rw_lock_create_func(
lock->mutex.cfile_name = cfile_name; lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline; lock->mutex.cline = cline;
lock->mutex.cmutex_name = cmutex_name;
lock->mutex.mutex_type = 1;
rw_lock_set_waiters(lock, 0); rw_lock_set_waiters(lock, 0);
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
lock->writer_count = 0; lock->writer_count = 0;
......
This diff is collapsed.
...@@ -73,6 +73,21 @@ ut_time(void) ...@@ -73,6 +73,21 @@ ut_time(void)
return(time(NULL)); return(time(NULL));
} }
/**************************************************************
Returns system time. We do not specify the format of the time returned:
the only way to manipulate it is to use the function ut_difftime. */
void
ut_usectime(ulint* sec, ulint* ms)
/*=========*/
{
struct timeval tv;
gettimeofday(&tv,NULL);
*sec = (ulint) tv.tv_sec;
*ms = (ulint) tv.tv_usec;
return;
}
/************************************************************** /**************************************************************
Returns the difference of two times in seconds. */ Returns the difference of two times in seconds. */
......
...@@ -1700,5 +1700,20 @@ Innodb_rows_read 80161 ...@@ -1700,5 +1700,20 @@ Innodb_rows_read 80161
show status like "Innodb_rows_updated"; show status like "Innodb_rows_updated";
Variable_name Value Variable_name Value
Innodb_rows_updated 29530 Innodb_rows_updated 29530
show status like "Innodb_row_lock_waits";
Variable_name Value
Innodb_row_lock_waits 0
show status like "Innodb_row_lock_current_waits";
Variable_name Value
Innodb_row_lock_current_waits 0
show status like "Innodb_row_lock_time";
Variable_name Value
Innodb_row_lock_time 0
show status like "Innodb_row_lock_time_max";
Variable_name Value
Innodb_row_lock_time_max 0
show status like "Innodb_row_lock_time_avg";
Variable_name Value
Innodb_row_lock_time_avg 0
create table t1 (v varchar(16384)) engine=innodb; create table t1 (v varchar(16384)) engine=innodb;
ERROR 42000: Column length too big for column 'v' (max = 255); use BLOB instead ERROR 42000: Column length too big for column 'v' (max = 255); use BLOB instead
...@@ -137,6 +137,14 @@ set global concurrent_insert=DEFAULT; ...@@ -137,6 +137,14 @@ set global concurrent_insert=DEFAULT;
show variables like 'concurrent_insert'; show variables like 'concurrent_insert';
Variable_name Value Variable_name Value
concurrent_insert ON concurrent_insert ON
set global timed_mutexes=1;
show variables like 'timed_mutexes';
Variable_name Value
timed_mutexes ON
set global timed_mutexes=0;
show variables like 'timed_mutexes';
Variable_name Value
timed_mutexes OFF
set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="INNODB"; set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="INNODB";
show local variables like 'storage_engine'; show local variables like 'storage_engine';
Variable_name Value Variable_name Value
......
...@@ -1210,6 +1210,14 @@ show status like "Innodb_rows_deleted"; ...@@ -1210,6 +1210,14 @@ show status like "Innodb_rows_deleted";
show status like "Innodb_rows_inserted"; show status like "Innodb_rows_inserted";
show status like "Innodb_rows_read"; show status like "Innodb_rows_read";
show status like "Innodb_rows_updated"; show status like "Innodb_rows_updated";
# Test for row locks InnoDB status variables.
show status like "Innodb_row_lock_waits";
show status like "Innodb_row_lock_current_waits";
show status like "Innodb_row_lock_time";
show status like "Innodb_row_lock_time_max";
show status like "Innodb_row_lock_time_avg";
# #
# Test varchar # Test varchar
# #
......
...@@ -83,6 +83,12 @@ show variables like 'concurrent_insert'; ...@@ -83,6 +83,12 @@ show variables like 'concurrent_insert';
set global concurrent_insert=DEFAULT; set global concurrent_insert=DEFAULT;
show variables like 'concurrent_insert'; show variables like 'concurrent_insert';
set global timed_mutexes=1;
show variables like 'timed_mutexes';
set global timed_mutexes=0;
show variables like 'timed_mutexes';
set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="INNODB"; set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="INNODB";
show local variables like 'storage_engine'; show local variables like 'storage_engine';
show global variables like 'storage_engine'; show global variables like 'storage_engine';
......
...@@ -231,6 +231,16 @@ struct show_var_st innodb_status_variables[]= { ...@@ -231,6 +231,16 @@ struct show_var_st innodb_status_variables[]= {
(char*) &export_vars.innodb_pages_read, SHOW_LONG}, (char*) &export_vars.innodb_pages_read, SHOW_LONG},
{"pages_written", {"pages_written",
(char*) &export_vars.innodb_pages_written, SHOW_LONG}, (char*) &export_vars.innodb_pages_written, SHOW_LONG},
{"row_lock_waits",
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG},
{"row_lock_current_waits",
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
{"row_lock_time",
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
{"row_lock_time_max",
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG},
{"row_lock_time_avg",
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG},
{"rows_deleted", {"rows_deleted",
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG}, (char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
{"rows_inserted", {"rows_inserted",
...@@ -5505,6 +5515,103 @@ innodb_show_status( ...@@ -5505,6 +5515,103 @@ innodb_show_status(
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
/****************************************************************************
Implements the SHOW MUTEX STATUS command. . */
bool
innodb_mutex_show_status(
/*===============*/
THD* thd) /* in: the MySQL query thread of the caller */
{
Protocol *protocol= thd->protocol;
List<Item> field_list;
mutex_t* mutex;
const char* file_name;
ulint line;
ulint rw_lock_count= 0;
ulint rw_lock_count_spin_loop= 0;
ulint rw_lock_count_spin_rounds= 0;
ulint rw_lock_count_os_wait= 0;
ulint rw_lock_count_os_yield= 0;
ulonglong rw_lock_wait_time= 0;
DBUG_ENTER("innodb_mutex_show_status");
field_list.push_back(new Item_empty_string("Mutex", FN_REFLEN));
field_list.push_back(new Item_empty_string("Module", FN_REFLEN));
field_list.push_back(new Item_uint("Count", 21));
field_list.push_back(new Item_uint("Spin_waits", 21));
field_list.push_back(new Item_uint("Spin_rounds", 21));
field_list.push_back(new Item_uint("OS_waits", 21));
field_list.push_back(new Item_uint("OS_yields", 21));
field_list.push_back(new Item_uint("OS_waits_time", 21));
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
// mutex_enter(&mutex_list_mutex);
mutex = UT_LIST_GET_FIRST(mutex_list);
while ( mutex != NULL )
{
if (mutex->mutex_type != 1)
{
if (mutex->count_using > 0)
{
protocol->prepare_for_resend();
protocol->store(mutex->cmutex_name, system_charset_info);
protocol->store(mutex->cfile_name, system_charset_info);
protocol->store((ulonglong)mutex->count_using);
protocol->store((ulonglong)mutex->count_spin_loop);
protocol->store((ulonglong)mutex->count_spin_rounds);
protocol->store((ulonglong)mutex->count_os_wait);
protocol->store((ulonglong)mutex->count_os_yield);
protocol->store((ulonglong)mutex->lspent_time/1000);
if (protocol->write())
{
// mutex_exit(&mutex_list_mutex);
DBUG_RETURN(1);
}
}
}
else
{
rw_lock_count += mutex->count_using;
rw_lock_count_spin_loop += mutex->count_spin_loop;
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
rw_lock_count_os_wait += mutex->count_os_wait;
rw_lock_count_os_yield += mutex->count_os_yield;
rw_lock_wait_time += mutex->lspent_time;
}
mutex = UT_LIST_GET_NEXT(list, mutex);
}
protocol->prepare_for_resend();
protocol->store("rw_lock_mutexes", system_charset_info);
protocol->store("", system_charset_info);
protocol->store((ulonglong)rw_lock_count);
protocol->store((ulonglong)rw_lock_count_spin_loop);
protocol->store((ulonglong)rw_lock_count_spin_rounds);
protocol->store((ulonglong)rw_lock_count_os_wait);
protocol->store((ulonglong)rw_lock_count_os_yield);
protocol->store((ulonglong)rw_lock_wait_time/1000);
if (protocol->write())
{
// mutex_exit(&mutex_list_mutex);
DBUG_RETURN(1);
}
// mutex_exit(&mutex_list_mutex);
send_eof(thd);
DBUG_RETURN(FALSE);
}
/**************************************************************************** /****************************************************************************
Handling the shared INNOBASE_SHARE structure that is needed to provide table Handling the shared INNOBASE_SHARE structure that is needed to provide table
locking. locking.
......
...@@ -242,6 +242,7 @@ int innobase_savepoint( ...@@ -242,6 +242,7 @@ int innobase_savepoint(
int innobase_close_connection(THD *thd); int innobase_close_connection(THD *thd);
int innobase_drop_database(char *path); int innobase_drop_database(char *path);
bool innodb_show_status(THD* thd); bool innodb_show_status(THD* thd);
bool innodb_mutex_show_status(THD* thd);
void innodb_export_status(void); void innodb_export_status(void);
my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name, my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
......
...@@ -323,6 +323,7 @@ static SYMBOL symbols[] = { ...@@ -323,6 +323,7 @@ static SYMBOL symbols[] = {
{ "MULTILINESTRING", SYM(MULTILINESTRING)}, { "MULTILINESTRING", SYM(MULTILINESTRING)},
{ "MULTIPOINT", SYM(MULTIPOINT)}, { "MULTIPOINT", SYM(MULTIPOINT)},
{ "MULTIPOLYGON", SYM(MULTIPOLYGON)}, { "MULTIPOLYGON", SYM(MULTIPOLYGON)},
{ "MUTEX", SYM(MUTEX_SYM)},
{ "NAME", SYM(NAME_SYM)}, { "NAME", SYM(NAME_SYM)},
{ "NAMES", SYM(NAMES_SYM)}, { "NAMES", SYM(NAMES_SYM)},
{ "NATIONAL", SYM(NATIONAL_SYM)}, { "NATIONAL", SYM(NATIONAL_SYM)},
......
...@@ -998,6 +998,7 @@ extern ulong table_cache_size; ...@@ -998,6 +998,7 @@ extern ulong table_cache_size;
extern ulong max_connections,max_connect_errors, connect_timeout; extern ulong max_connections,max_connect_errors, connect_timeout;
extern ulong slave_net_timeout; extern ulong slave_net_timeout;
extern ulong max_user_connections; extern ulong max_user_connections;
extern my_bool timed_mutexes;
extern ulong what_to_log,flush_time; extern ulong what_to_log,flush_time;
extern ulong query_buff_size, thread_stack,thread_stack_min; extern ulong query_buff_size, thread_stack,thread_stack_min;
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit; extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
......
...@@ -325,6 +325,7 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ...@@ -325,6 +325,7 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
ulong max_connections,max_used_connections, ulong max_connections,max_used_connections,
max_connect_errors, max_user_connections = 0; max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid; ulong thread_id=1L,current_pid;
my_bool timed_mutexes= 0;
ulong slow_launch_threads = 0, sync_binlog_period; ulong slow_launch_threads = 0, sync_binlog_period;
ulong expire_logs_days = 0; ulong expire_logs_days = 0;
ulong rpl_recovery_rank=0; ulong rpl_recovery_rank=0;
...@@ -4200,7 +4201,8 @@ enum options_mysqld ...@@ -4200,7 +4201,8 @@ enum options_mysqld
OPT_OPTIMIZER_PRUNE_LEVEL, OPT_OPTIMIZER_PRUNE_LEVEL,
OPT_UPDATABLE_VIEWS_WITH_LIMIT, OPT_UPDATABLE_VIEWS_WITH_LIMIT,
OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET, OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
OPT_ENABLE_LARGE_PAGES OPT_ENABLE_LARGE_PAGES,
OPT_TIMED_MUTEXES
}; };
...@@ -4799,6 +4801,10 @@ log and this option does nothing anymore.", ...@@ -4799,6 +4801,10 @@ log and this option does nothing anymore.",
"Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.", "Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
(gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1, (gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0}, 0, 0, 0, 0, 0},
{"timed_mutexes", OPT_TIMED_MUTEXES,
"Specify whether to time mutexes (only InnoDB mutexes are currently supported)",
(gptr*) &timed_mutexes, (gptr*) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
0, 0, 0, 0, 0},
{"tmpdir", 't', {"tmpdir", 't',
"Path for temporary files. Several paths may be specified, separated by a " "Path for temporary files. Several paths may be specified, separated by a "
#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
......
...@@ -361,6 +361,8 @@ sys_var_thd_enum sys_tx_isolation("tx_isolation", ...@@ -361,6 +361,8 @@ sys_var_thd_enum sys_tx_isolation("tx_isolation",
fix_tx_isolation); fix_tx_isolation);
sys_var_thd_ulong sys_tmp_table_size("tmp_table_size", sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
&SV::tmp_table_size); &SV::tmp_table_size);
sys_var_bool_ptr sys_timed_mutexes("timed_mutexes",
&timed_mutexes);
sys_var_thd_ulong sys_net_wait_timeout("wait_timeout", sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
&SV::net_wait_timeout); &SV::net_wait_timeout);
...@@ -635,6 +637,7 @@ sys_var *sys_variables[]= ...@@ -635,6 +637,7 @@ sys_var *sys_variables[]=
&sys_table_type, &sys_table_type,
&sys_thread_cache_size, &sys_thread_cache_size,
&sys_time_format, &sys_time_format,
&sys_timed_mutexes,
&sys_timestamp, &sys_timestamp,
&sys_time_zone, &sys_time_zone,
&sys_tmp_table_size, &sys_tmp_table_size,
...@@ -901,6 +904,7 @@ struct show_var_st init_vars[]= { ...@@ -901,6 +904,7 @@ struct show_var_st init_vars[]= {
{"thread_stack", (char*) &thread_stack, SHOW_LONG}, {"thread_stack", (char*) &thread_stack, SHOW_LONG},
{sys_time_format.name, (char*) &sys_time_format, SHOW_SYS}, {sys_time_format.name, (char*) &sys_time_format, SHOW_SYS},
{"time_zone", (char*) &sys_time_zone, SHOW_SYS}, {"time_zone", (char*) &sys_time_zone, SHOW_SYS},
{sys_timed_mutexes.name, (char*) &sys_timed_mutexes, SHOW_SYS},
{sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS}, {sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS},
{"tmpdir", (char*) &opt_mysql_tmpdir, SHOW_CHAR_PTR}, {"tmpdir", (char*) &opt_mysql_tmpdir, SHOW_CHAR_PTR},
{sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size, {sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size,
......
...@@ -53,7 +53,7 @@ enum enum_sql_command { ...@@ -53,7 +53,7 @@ enum enum_sql_command {
SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS, SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS, SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_INNODB_STATUS, SQLCOM_SHOW_INNODB_STATUS, SQLCOM_SHOW_MUTEX_STATUS,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS, SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
......
...@@ -2488,6 +2488,13 @@ mysql_execute_command(THD *thd) ...@@ -2488,6 +2488,13 @@ mysql_execute_command(THD *thd)
res = innodb_show_status(thd); res = innodb_show_status(thd);
break; break;
} }
case SQLCOM_SHOW_MUTEX_STATUS:
{
if (check_global_access(thd, SUPER_ACL))
goto error;
res = innodb_mutex_show_status(thd);
break;
}
#endif #endif
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
case SQLCOM_LOAD_MASTER_TABLE: case SQLCOM_LOAD_MASTER_TABLE:
......
...@@ -337,6 +337,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -337,6 +337,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MAX_UPDATES_PER_HOUR %token MAX_UPDATES_PER_HOUR
%token MEDIUM_SYM %token MEDIUM_SYM
%token MIN_ROWS %token MIN_ROWS
%token MUTEX_SYM
%token NAMES_SYM %token NAMES_SYM
%token NAME_SYM %token NAME_SYM
%token NATIONAL_SYM %token NATIONAL_SYM
...@@ -5986,6 +5987,8 @@ show_param: ...@@ -5986,6 +5987,8 @@ show_param:
} }
| INNOBASE_SYM STATUS_SYM | INNOBASE_SYM STATUS_SYM
{ Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS; WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS"); } { Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS; WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS"); }
| MUTEX_SYM STATUS_SYM
{ Lex->sql_command = SQLCOM_SHOW_MUTEX_STATUS; }
| opt_full PROCESSLIST_SYM | opt_full PROCESSLIST_SYM
{ Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;} { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
| opt_var_type VARIABLES wild | opt_var_type VARIABLES wild
...@@ -6987,6 +6990,7 @@ keyword: ...@@ -6987,6 +6990,7 @@ keyword:
| MULTILINESTRING {} | MULTILINESTRING {}
| MULTIPOINT {} | MULTIPOINT {}
| MULTIPOLYGON {} | MULTIPOLYGON {}
| MUTEX_SYM {}
| NAME_SYM {} | NAME_SYM {}
| NAMES_SYM {} | NAMES_SYM {}
| NATIONAL_SYM {} | NATIONAL_SYM {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment