Commit 6fe27b5d authored by inaam's avatar inaam

branches/zip: internal mantis issue#49

This is to fix an unintended side effect of file_format_check changes.
We were reading the trx system page (TRX_SYS_PAGE_NO) before starting
recovery and that resulted in redo logs not being applied to the page.
The fix is to force a reread by calling buf_pool_invalidate().
This, however, made necessary that any writes to page are deferred to
until after the redo log application.

Reviewed by: Sunny
parent ccf2f704
......@@ -310,6 +310,15 @@ UNIV_INTERN
void
trx_sys_file_format_close(void);
/*===========================*/
/************************************************************************
Tags the system table space with minimum format id if it has not been
tagged yet.
WARNING: This function is only called during the startup and AFTER the
redo log application during recovery has finished. */
UNIV_INTERN
void
trx_sys_file_format_tag_init(void);
/*==============================*/
/*********************************************************************
Get the name representation of the file format from its id. */
UNIV_INTERN
......@@ -319,14 +328,16 @@ trx_sys_file_format_id_to_name(
/* out: pointer to the name */
const uint id); /* in: id of the file format */
/*********************************************************************
Set the file format tag unconditonally. */
Set the file format id unconditionally except if it's already the
same value. */
UNIV_INTERN
ibool
trx_sys_file_format_max_set(
/*===========================*/
/*========================*/
/* out: TRUE if value updated */
ulint file_format, /* in: file format id */
char** name); /* out: max format name */
ulint format_id, /* in: file format id */
char** name); /* out: max file format name or
NULL if not needed. */
/*********************************************************************
Get the name representation of the file format from its id. */
UNIV_INTERN
......
......@@ -1462,7 +1462,17 @@ innobase_start_or_create_for_mysql(void)
} else {
/* Check if we support the max format that is stamped
on the system tablespace. */
on the system tablespace.
Note: We are NOT allowed to make any modifications to
the TRX_SYS_PAGE_NO page before recovery because this
page also contains the max_trx_id etc. important system
variables that are required for recovery. We need to
ensure that we return the system to a state where normal
recovery is guaranteed to work. We do this by
invalidating the buffer cache, this will force the
reread of the page and restoration to it's last known
consistent state, this is REQUIRED for the recovery
process to work. */
err = trx_sys_file_format_max_check(
srv_check_file_format_at_startup);
......@@ -1470,6 +1480,13 @@ innobase_start_or_create_for_mysql(void)
return(err);
}
/* Invalidate the buffer pool to ensure that we reread
the page that we read above, during recovery.
Note that this is not as heavy weight as it seems. At
this point there will be only ONE page in the buf_LRU
and there must be no page in the buf_flush list. */
buf_pool_invalidate();
/* We always try to do a recovery, even if the database had
been shut down normally: this is the normal startup path */
......@@ -1526,6 +1543,13 @@ innobase_start_or_create_for_mysql(void)
are initialized in trx_sys_init_at_db_start(). */
recv_recovery_from_checkpoint_finish();
/* It is possible that file_format tag has never
been set. In this case we initialize it to minimum
value. Important to note that we can do it ONLY after
we have finished the recovery process so that the
image of TRX_SYS_PAGE_NO is not stale. */
trx_sys_file_format_tag_init();
}
if (!create_new_db && sum_of_new_sizes > 0) {
......
......@@ -1106,7 +1106,8 @@ static
ulint
trx_sys_file_format_max_read(void)
/*==============================*/
/* out: the file format */
/* out: the file format or
ULINT_UNDEFINED if not set. */
{
mtr_t mtr;
const byte* ptr;
......@@ -1131,10 +1132,8 @@ trx_sys_file_format_max_read(void)
if (file_format_id.high != TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_HIGH
|| format_id >= FILE_FORMAT_NAME_N) {
/* Either it has never been tagged, or garbage in it.
Reset the tag in either case. */
format_id = DICT_TF_FORMAT_51;
trx_sys_file_format_max_write(format_id, NULL);
/* Either it has never been tagged, or garbage in it. */
return(ULINT_UNDEFINED);
}
return(format_id);
......@@ -1170,6 +1169,11 @@ trx_sys_file_format_max_check(
recover if the file format is not supported by the engine
unless forced by the user. */
format_id = trx_sys_file_format_max_read();
if (format_id == ULINT_UNDEFINED) {
/* Format ID was not set. Set it to minimum possible
value. */
format_id = DICT_TF_FORMAT_51;
}
ut_print_timestamp(stderr);
fprintf(stderr,
......@@ -1212,11 +1216,11 @@ trx_sys_file_format_max_set(
/*========================*/
/* out: TRUE if value updated */
ulint format_id, /* in: file format id */
char** name) /* out: max file format name */
char** name) /* out: max file format name or
NULL if not needed. */
{
ibool ret = FALSE;
ut_a(name);
ut_a(format_id <= DICT_TF_FORMAT_MAX);
mutex_enter(&file_format_max.mutex);
......@@ -1232,6 +1236,26 @@ trx_sys_file_format_max_set(
return(ret);
}
/************************************************************************
Tags the system table space with minimum format id if it has not been
tagged yet.
WARNING: This function is only called during the startup and AFTER the
redo log application during recovery has finished. */
UNIV_INTERN
void
trx_sys_file_format_tag_init(void)
/*==============================*/
{
ulint format_id;
format_id = trx_sys_file_format_max_read();
/* If format_id is not set then set it to the minimum. */
if (format_id == ULINT_UNDEFINED) {
trx_sys_file_format_max_set(DICT_TF_FORMAT_51, NULL);
}
}
/************************************************************************
Update the file format tag in the tablespace only if the given format id
is greater than the known max id. */
......
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