Commit 97c7996e 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 cb08544b
......@@ -1922,21 +1922,32 @@ srv_export_innodb_status(void)
export_vars.innodb_rows_deleted = srv_n_rows_deleted;
#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;
} else {
export_vars.innodb_purge_trx_id_age =
ut_dulint_minus(trx_sys->max_trx_id, purge_sys->done_trx_no);
}
{
dulint done_trx_no;
dulint up_limit_id;
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
|| ut_dulint_cmp(trx_sys->max_trx_id,
purge_sys->view->up_limit_id) < 0) {
export_vars.innodb_purge_view_trx_id_age = 0;
} else {
export_vars.innodb_purge_view_trx_id_age =
ut_dulint_minus(trx_sys->max_trx_id,
purge_sys->view->up_limit_id);
if (ut_dulint_is_zero(up_limit_id)
|| ut_dulint_cmp(trx_sys->max_trx_id, up_limit_id) < 0) {
export_vars.innodb_purge_view_trx_id_age = 0;
} else {
export_vars.innodb_purge_view_trx_id_age =
ut_dulint_minus(trx_sys->max_trx_id,
up_limit_id);
}
}
#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) 2009, Percona Inc.
......@@ -257,7 +257,7 @@ UNIV_INTERN ulint srv_data_read = 0;
/* Internal setting for "innodb_stats_method". Decides how InnoDB treats
NULL value when collecting statistics. By default, it is set to
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) */
UNIV_INTERN ulint srv_data_written = 0;
......@@ -1978,21 +1978,32 @@ srv_export_innodb_status(void)
export_vars.innodb_rows_deleted = srv_n_rows_deleted;
#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;
} else {
export_vars.innodb_purge_trx_id_age =
ut_dulint_minus(trx_sys->max_trx_id, purge_sys->done_trx_no);
}
{
dulint done_trx_no;
dulint up_limit_id;
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
|| ut_dulint_cmp(trx_sys->max_trx_id,
purge_sys->view->up_limit_id) < 0) {
export_vars.innodb_purge_view_trx_id_age = 0;
} else {
export_vars.innodb_purge_view_trx_id_age =
ut_dulint_minus(trx_sys->max_trx_id,
purge_sys->view->up_limit_id);
if (ut_dulint_is_zero(up_limit_id)
|| ut_dulint_cmp(trx_sys->max_trx_id, up_limit_id) < 0) {
export_vars.innodb_purge_view_trx_id_age = 0;
} else {
export_vars.innodb_purge_view_trx_id_age =
ut_dulint_minus(trx_sys->max_trx_id,
up_limit_id);
}
}
#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