Commit 7f6fb4d9 authored by joreland@mysql.com's avatar joreland@mysql.com

Merge mysql.com:/home/jonas/src/mysql-5.0

into mysql.com:/home/jonas/src/mysql-5.0-ndb
parents 8f2d0ec1 7b7113a9
...@@ -239,6 +239,7 @@ ulli@morbus.(none) ...@@ -239,6 +239,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;
...@@ -1688,15 +1721,14 @@ srv_printf_innodb_monitor( ...@@ -1688,15 +1721,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);
} }
...@@ -1745,11 +1777,19 @@ srv_export_innodb_status(void) ...@@ -1745,11 +1777,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;
......
...@@ -129,11 +129,6 @@ sync_array_t* sync_primary_wait_array; ...@@ -129,11 +129,6 @@ sync_array_t* sync_primary_wait_array;
/* This variable is set to TRUE when sync_init is called */ /* This variable is set to TRUE when sync_init is called */
ibool sync_initialized = FALSE; ibool sync_initialized = FALSE;
/* 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;
typedef struct sync_level_struct sync_level_t; typedef struct sync_level_struct sync_level_t;
typedef struct sync_thread_struct sync_thread_t; typedef struct sync_thread_struct sync_thread_t;
...@@ -202,7 +197,8 @@ mutex_create_func( ...@@ -202,7 +197,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 */
{ {
#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
mutex_reset_lock_word(mutex); mutex_reset_lock_word(mutex);
...@@ -219,6 +215,16 @@ mutex_create_func( ...@@ -219,6 +215,16 @@ mutex_create_func(
mutex->level = SYNC_LEVEL_NONE; mutex->level = SYNC_LEVEL_NONE;
mutex->cfile_name = cfile_name; mutex->cfile_name = cfile_name;
mutex->cline = cline; mutex->cline = cline;
mutex->cmutex_name= cmutex_name;
mutex->count_using= 0;
mutex->mutex_type= 0;
mutex->lspent_time= 0;
mutex->lmax_spent_time= 0;
mutex->count_spin_loop= 0;
mutex->count_spin_rounds= 0;
mutex->count_os_wait= 0;
mutex->count_os_yield= 0;
/* Check that lock_word is aligned; this is important on Intel */ /* Check that lock_word is aligned; this is important on Intel */
ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0); ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
...@@ -355,135 +361,180 @@ for the mutex before suspending the thread. */ ...@@ -355,135 +361,180 @@ for the mutex before suspending the thread. */
void void
mutex_spin_wait( mutex_spin_wait(
/*============*/ /*============*/
mutex_t* mutex, /* in: pointer to mutex */ mutex_t* mutex, /* in: pointer to mutex */
const char* file_name, /* in: file name where const char* file_name, /* in: file name where
mutex requested */ mutex requested */
ulint line) /* in: line where requested */ ulint line) /* in: line where requested */
{ {
ulint index; /* index of the reserved wait cell */ ulint index; /* index of the reserved wait cell */
ulint i; /* spin round count */ ulint i; /* spin round count */
ib_longlong lstart_time, lfinish_time; /* for timing os_wait */
ut_ad(mutex); ulint ltime_diff;
ulint sec;
ulint ms;
mutex_loop: uint timer_started = 0;
i = 0; ut_ad(mutex);
/* Spin waiting for the lock word to become zero. Note that we do not mutex_loop:
have to assume that the read access to the lock word is atomic, as the
actual locking is always committed with atomic test-and-set. In
reality, however, all processors probably have an atomic read of a
memory word. */
spin_loop:
mutex_spin_wait_count++;
while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { i = 0;
if (srv_spin_wait_delay) { /* Spin waiting for the lock word to become zero. Note that we do not
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); have to assume that the read access to the lock word is atomic, as the
} actual locking is always committed with atomic test-and-set. In
reality, however, all processors probably have an atomic read of a
i++; memory word. */
}
if (i == SYNC_SPIN_ROUNDS) { spin_loop:
os_thread_yield(); mutex_spin_wait_count++;
} mutex->count_spin_loop++;
while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS)
{
if (srv_spin_wait_delay)
{
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
}
i++;
}
if (i == SYNC_SPIN_ROUNDS)
{
mutex->count_os_yield++;
if (timed_mutexes == 1 && timer_started==0)
{
ut_usectime(&sec, &ms);
lstart_time= (ib_longlong)sec * 1000000 + ms;
timer_started = 1;
}
os_thread_yield();
}
#ifdef UNIV_SRV_PRINT_LATCH_WAITS
fprintf(stderr,
"Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
#endif
if (srv_print_latch_waits) { mutex_spin_round_count += i;
fprintf(stderr,
"Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
}
mutex_spin_round_count += i; mutex->count_spin_rounds += i;
if (mutex_test_and_set(mutex) == 0) { if (mutex_test_and_set(mutex) == 0)
/* Succeeded! */ {
/* Succeeded! */
#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
return; goto finish_timing;
} }
/* We may end up with a situation where lock_word is /* We may end up with a situation where lock_word is
0 but the OS fast mutex is still reserved. On FreeBSD 0 but the OS fast mutex is still reserved. On FreeBSD
the OS does not seem to schedule a thread which is constantly the OS does not seem to schedule a thread which is constantly
calling pthread_mutex_trylock (in mutex_test_and_set calling pthread_mutex_trylock (in mutex_test_and_set
implementation). Then we could end up spinning here indefinitely. implementation). Then we could end up spinning here indefinitely.
The following 'i++' stops this infinite spin. */ The following 'i++' stops this infinite spin. */
i++; i++;
if (i < SYNC_SPIN_ROUNDS) {
goto spin_loop; if (i < SYNC_SPIN_ROUNDS)
} {
goto spin_loop;
}
sync_array_reserve_cell(sync_primary_wait_array, mutex, sync_array_reserve_cell(sync_primary_wait_array, mutex,
SYNC_MUTEX, SYNC_MUTEX, file_name, line, &index);
file_name, line,
&index);
mutex_system_call_count++; mutex_system_call_count++;
/* The memory order of the array reservation and the change in the /* The memory order of the array reservation and the change in the
waiters field is important: when we suspend a thread, we first waiters field is important: when we suspend a thread, we first
reserve the cell and then set waiters field to 1. When threads are reserve the cell and then set waiters field to 1. When threads are
released in mutex_exit, the waiters field is first set to zero and released in mutex_exit, the waiters field is first set to zero and
then the event is set to the signaled state. */ then the event is set to the signaled state. */
mutex_set_waiters(mutex, 1); mutex_set_waiters(mutex, 1);
/* Try to reserve still a few times */ /* Try to reserve still a few times */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++)
if (mutex_test_and_set(mutex) == 0) { {
if (mutex_test_and_set(mutex) == 0)
{
/* Succeeded! Free the reserved wait cell */
/* Succeeded! Free the reserved wait cell */ sync_array_free_cell(sync_primary_wait_array, index);
sync_array_free_cell(sync_primary_wait_array, index);
#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
if (srv_print_latch_waits) { #ifdef UNIV_SRV_PRINT_LATCH_WAITS
fprintf(stderr, fprintf(stderr, "Thread %lu spin wait succeeds at 2:"
"Thread %lu spin wait succeeds at 2:" " mutex at %p\n",
" mutex at %p\n", (ulong) os_thread_pf(os_thread_get_curr_id()),
(ulong) os_thread_pf(os_thread_get_curr_id()), mutex);
mutex); #endif
}
return;
/* Note that in this case we leave the waiters field goto finish_timing;
set to 1. We cannot reset it to zero, as we do not know
if there are other waiters. */
}
}
/* Now we know that there has been some thread holding the mutex /* Note that in this case we leave the waiters field
after the change in the wait array and the waiters field was made. set to 1. We cannot reset it to zero, as we do not know
Now there is no risk of infinite wait on the event. */ if there are other waiters. */
}
}
if (srv_print_latch_waits) { /* Now we know that there has been some thread holding the mutex
fprintf(stderr, after the change in the wait array and the waiters field was made.
"Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n", Now there is no risk of infinite wait on the event. */
(ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
}
mutex_system_call_count++;
mutex_os_wait_count++;
sync_array_wait_event(sync_primary_wait_array, index); #ifdef UNIV_SRV_PRINT_LATCH_WAITS
fprintf(stderr,
"Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
(ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
#endif
goto mutex_loop; mutex_system_call_count++;
mutex_os_wait_count++;
mutex->count_os_wait++;
/*
!!!!! Sometimes os_wait can be called without os_thread_yield
*/
if (timed_mutexes == 1 && timer_started==0)
{
ut_usectime(&sec, &ms);
lstart_time= (ib_longlong)sec * 1000000 + ms;
timer_started = 1;
}
sync_array_wait_event(sync_primary_wait_array, index);
goto mutex_loop;
finish_timing:
if (timed_mutexes == 1 && timer_started==1)
{
ut_usectime(&sec, &ms);
lfinish_time= (ib_longlong)sec * 1000000 + ms;
ltime_diff= lfinish_time - lstart_time;
mutex->lspent_time += ltime_diff;
if (mutex->lmax_spent_time < ltime_diff)
{
mutex->lmax_spent_time= ltime_diff;
}
}
return;
} }
/********************************************************************** /**********************************************************************
...@@ -555,6 +606,7 @@ mutex_set_level( ...@@ -555,6 +606,7 @@ mutex_set_level(
mutex->level = level; mutex->level = level;
} }
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
/********************************************************************** /**********************************************************************
Checks that the current thread owns the mutex. Works only in the debug Checks that the current thread owns the mutex. Works only in the debug
......
...@@ -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';
......
...@@ -8,14 +8,6 @@ ...@@ -8,14 +8,6 @@
static const char* opt_connect_str= 0; static const char* opt_connect_str= 0;
static const char* _dbname = "TEST_DB"; static const char* _dbname = "TEST_DB";
static int g_loops = 7; static int g_loops = 7;
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
{ "database", 'd', "Name of database table is in",
(gptr*) &_dbname, (gptr*) &_dbname, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
static void print_version() static void print_version()
{ {
...@@ -29,8 +21,6 @@ static void usage() ...@@ -29,8 +21,6 @@ static void usage()
"This program list all properties of table(s) in NDB Cluster.\n"\ "This program list all properties of table(s) in NDB Cluster.\n"\
" ex: desc T1 T2 T4\n"; " ex: desc T1 T2 T4\n";
print_version(); print_version();
my_print_help(my_long_options);
my_print_variables(my_long_options);
} }
static my_bool static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)), get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
...@@ -63,8 +53,6 @@ main(int argc, char** argv){ ...@@ -63,8 +53,6 @@ main(int argc, char** argv){
const char *load_default_groups[]= { "mysql_cluster",0 }; const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv); load_defaults("my",load_default_groups,&argc,&argv);
int ho_error; int ho_error;
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
Ndb_cluster_connection con(opt_connect_str); Ndb_cluster_connection con(opt_connect_str);
if(con.connect(12, 5, 1)) if(con.connect(12, 5, 1))
......
...@@ -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,107 @@ innodb_show_status( ...@@ -5505,6 +5515,107 @@ 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);
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
mutex_enter(&mutex_list_mutex);
#endif
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())
{
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
mutex_exit(&mutex_list_mutex);
#endif
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())
{
DBUG_RETURN(1);
}
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
mutex_exit(&mutex_list_mutex);
#endif
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)},
......
...@@ -996,6 +996,7 @@ extern ulong table_cache_size; ...@@ -996,6 +996,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;
......
...@@ -334,6 +334,7 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ...@@ -334,6 +334,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;
...@@ -4213,7 +4214,8 @@ enum options_mysqld ...@@ -4213,7 +4214,8 @@ enum options_mysqld
OPT_UPDATABLE_VIEWS_WITH_LIMIT, OPT_UPDATABLE_VIEWS_WITH_LIMIT,
OPT_SP_AUTOMATIC_PRIVILEGES, OPT_SP_AUTOMATIC_PRIVILEGES,
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
}; };
...@@ -4838,6 +4840,10 @@ log and this option does nothing anymore.", ...@@ -4838,6 +4840,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__)
......
...@@ -365,6 +365,8 @@ sys_var_thd_enum sys_tx_isolation("tx_isolation", ...@@ -365,6 +365,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);
...@@ -636,6 +638,7 @@ sys_var *sys_variables[]= ...@@ -636,6 +638,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,
...@@ -903,6 +906,7 @@ struct show_var_st init_vars[]= { ...@@ -903,6 +906,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,
......
...@@ -2502,6 +2502,13 @@ mysql_execute_command(THD *thd) ...@@ -2502,6 +2502,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:
......
...@@ -336,6 +336,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -336,6 +336,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
...@@ -5997,6 +5998,8 @@ show_param: ...@@ -5997,6 +5998,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 ext_select_item_list wild_and_where | opt_var_type VARIABLES ext_select_item_list wild_and_where
...@@ -6998,6 +7001,7 @@ keyword: ...@@ -6998,6 +7001,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