Commit c91eb80e authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#16292043 RACE CONDITION IN SRV_EXPORT_INNODB_STATUS() WHEN ACCESSING PURGE_SYS->VIEW

srv_export_innodb_status(): Read the purge_sys fields while holding
purge_sys->latch.

Approved by Sunny Bains
parent 50000c3c
...@@ -1922,21 +1922,32 @@ srv_export_innodb_status(void) ...@@ -1922,21 +1922,32 @@ srv_export_innodb_status(void)
export_vars.innodb_rows_deleted = srv_n_rows_deleted; export_vars.innodb_rows_deleted = srv_n_rows_deleted;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (ut_dulint_cmp(trx_sys->max_trx_id, purge_sys->done_trx_no) < 0) { {
export_vars.innodb_purge_trx_id_age = 0; dulint done_trx_no;
} else { dulint up_limit_id;
export_vars.innodb_purge_trx_id_age =
ut_dulint_minus(trx_sys->max_trx_id, purge_sys->done_trx_no); rw_lock_s_lock(&purge_sys->latch);
} done_trx_no = purge_sys->done_trx_no;
up_limit_id = purge_sys->view
? purge_sys->view->up_limit_id
: ut_dulint_zero;
rw_lock_s_unlock(&purge_sys->latch);
if (ut_dulint_cmp(trx_sys->max_trx_id, done_trx_no) < 0) {
export_vars.innodb_purge_trx_id_age = 0;
} else {
export_vars.innodb_purge_trx_id_age = ut_dulint_minus(
trx_sys->max_trx_id, done_trx_no);
}
if (!purge_sys->view if (ut_dulint_is_zero(up_limit_id)
|| ut_dulint_cmp(trx_sys->max_trx_id, || ut_dulint_cmp(trx_sys->max_trx_id, up_limit_id) < 0) {
purge_sys->view->up_limit_id) < 0) { export_vars.innodb_purge_view_trx_id_age = 0;
export_vars.innodb_purge_view_trx_id_age = 0; } else {
} else { export_vars.innodb_purge_view_trx_id_age =
export_vars.innodb_purge_view_trx_id_age = ut_dulint_minus(trx_sys->max_trx_id,
ut_dulint_minus(trx_sys->max_trx_id, up_limit_id);
purge_sys->view->up_limit_id); }
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc. Copyright (c) 2009, Percona Inc.
...@@ -257,7 +257,7 @@ UNIV_INTERN ulint srv_data_read = 0; ...@@ -257,7 +257,7 @@ UNIV_INTERN ulint srv_data_read = 0;
/* Internal setting for "innodb_stats_method". Decides how InnoDB treats /* Internal setting for "innodb_stats_method". Decides how InnoDB treats
NULL value when collecting statistics. By default, it is set to NULL value when collecting statistics. By default, it is set to
SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */ SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */
ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL; UNIV_INTERN ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL;
/* here we count the amount of data written in total (in bytes) */ /* here we count the amount of data written in total (in bytes) */
UNIV_INTERN ulint srv_data_written = 0; UNIV_INTERN ulint srv_data_written = 0;
...@@ -1978,21 +1978,32 @@ srv_export_innodb_status(void) ...@@ -1978,21 +1978,32 @@ srv_export_innodb_status(void)
export_vars.innodb_rows_deleted = srv_n_rows_deleted; export_vars.innodb_rows_deleted = srv_n_rows_deleted;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (ut_dulint_cmp(trx_sys->max_trx_id, purge_sys->done_trx_no) < 0) { {
export_vars.innodb_purge_trx_id_age = 0; dulint done_trx_no;
} else { dulint up_limit_id;
export_vars.innodb_purge_trx_id_age =
ut_dulint_minus(trx_sys->max_trx_id, purge_sys->done_trx_no); rw_lock_s_lock(&purge_sys->latch);
} done_trx_no = purge_sys->done_trx_no;
up_limit_id = purge_sys->view
? purge_sys->view->up_limit_id
: ut_dulint_zero;
rw_lock_s_unlock(&purge_sys->latch);
if (ut_dulint_cmp(trx_sys->max_trx_id, done_trx_no) < 0) {
export_vars.innodb_purge_trx_id_age = 0;
} else {
export_vars.innodb_purge_trx_id_age = ut_dulint_minus(
trx_sys->max_trx_id, done_trx_no);
}
if (!purge_sys->view if (ut_dulint_is_zero(up_limit_id)
|| ut_dulint_cmp(trx_sys->max_trx_id, || ut_dulint_cmp(trx_sys->max_trx_id, up_limit_id) < 0) {
purge_sys->view->up_limit_id) < 0) { export_vars.innodb_purge_view_trx_id_age = 0;
export_vars.innodb_purge_view_trx_id_age = 0; } else {
} else { export_vars.innodb_purge_view_trx_id_age =
export_vars.innodb_purge_view_trx_id_age = ut_dulint_minus(trx_sys->max_trx_id,
ut_dulint_minus(trx_sys->max_trx_id, up_limit_id);
purge_sys->view->up_limit_id); }
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
......
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