From 8c7ef99bb24f9faa2e71b97178482606d83934bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 13 Nov 2014 11:24:19 +0200 Subject: [PATCH] MDEV-7100: InnoDB error monitor might unnecessary wait log_sys mutex Analysis: InnoDB error monitor is responsible to call every second sync_arr_wake_threads_if_sema_free() to wake up possible hanging threads if they are missed in mutex_signal_object. This is not possible if error monitor itself is on mutex/semaphore wait. We should avoid all unnecessary mutex/semaphore waits on error monitor. Currently error monitor calls function buf_flush_stat_update() that calls log_get_lsn() function and there we will try to get log_sys mutex. Better, solution for error monitor is that in buf_flush_stat_update() we will try to get lsn with mutex_enter_nowait() and if we did not get mutex do not update the stats. Fix: Use log_get_lsn_nowait() function on buf_flush_stat_update() function. If returned lsn is 0, we do not update flush stats. log_get_lsn_nowait() will use mutex_enter_nowait() and if we get mutex we return a correct lsn if not we return 0. --- storage/innobase/buf/buf0flu.c | 10 +++++++++- storage/innobase/include/log0log.ic | 10 +++++----- storage/xtradb/buf/buf0flu.c | 10 +++++++++- storage/xtradb/include/log0log.ic | 10 +++++----- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index 7abd014a364..da58d8392cf 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -2103,7 +2103,15 @@ buf_flush_stat_update(void) ib_uint64_t lsn; ulint n_flushed; - lsn = log_get_lsn(); + lsn = log_get_lsn_nowait(); + + /* log_get_lsn_nowait tries to get log_sys->mutex with + mutex_enter_nowait, if this does not succeed function + returns 0, do not use that value to update stats. */ + if (lsn == 0) { + return; + } + if (buf_flush_stat_cur.redo == 0) { /* First time around. Just update the current LSN and return. */ diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic index a55bbeff789..8c8dc096a10 100644 --- a/storage/innobase/include/log0log.ic +++ b/storage/innobase/include/log0log.ic @@ -419,14 +419,14 @@ lsn_t log_get_lsn_nowait(void) /*=============*/ { - lsn_t lsn; + lsn_t lsn=0; - if (mutex_enter_nowait(&(log_sys->mutex))) - return 0; + if (!mutex_enter_nowait(&(log_sys->mutex))) { - lsn = log_sys->lsn; + lsn = log_sys->lsn; - mutex_exit(&(log_sys->mutex)); + mutex_exit(&(log_sys->mutex)); + } return(lsn); } diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c index aa93053abae..43f6a4510a2 100644 --- a/storage/xtradb/buf/buf0flu.c +++ b/storage/xtradb/buf/buf0flu.c @@ -2214,7 +2214,15 @@ buf_flush_stat_update(void) ib_uint64_t lsn; ulint n_flushed; - lsn = log_get_lsn(); + lsn = log_get_lsn_nowait(); + + /* log_get_lsn_nowait tries to get log_sys->mutex with + mutex_enter_nowait, if this does not succeed function + returns 0, do not use that value to update stats. */ + if (lsn == 0) { + return; + } + if (buf_flush_stat_cur.redo == 0) { /* First time around. Just update the current LSN and return. */ diff --git a/storage/xtradb/include/log0log.ic b/storage/xtradb/include/log0log.ic index 82f1912c584..36bc5186c22 100644 --- a/storage/xtradb/include/log0log.ic +++ b/storage/xtradb/include/log0log.ic @@ -434,14 +434,14 @@ lsn_t log_get_lsn_nowait(void) /*=============*/ { - lsn_t lsn; + lsn_t lsn=0; - if (mutex_enter_nowait(&(log_sys->mutex))) - return 0; + if (!mutex_enter_nowait(&(log_sys->mutex))) { - lsn = log_sys->lsn; + lsn = log_sys->lsn; - mutex_exit(&(log_sys->mutex)); + mutex_exit(&(log_sys->mutex)); + } return(lsn); }