mirror of
https://github.com/MariaDB/server.git
synced 2025-01-21 22:34:18 +01:00
branches/zip:
Implement the system tablespace tagging described on the wiki: https://svn.innodb.com/innobase/InnoDB_version_and_feature_compatibility A brief description of the changes: * The file format tag will be saved in the trx system page, starting at (UNIV_PAGE_SIZE - 16) for 8 bytes. * The configuration parameter innodb_file_format_check is introduced. This variable can be set to on/off and any of the supported file formats in the configuration file, but can only be set to any of the supported file formats during runtime. The default is on. * During table create/open, check the current file format against the max in file_format_max. If the current file format is newer, update file_format_max and tag the system tablespace with the newer one in a normal mtr. * During startup, write the tag to the error log and check it against DICT_TF_FORMAT_MAX. Refuse to start with error, if -- DICT_TF_FORMAT_MAX < the tag, and -- innodb_file_format_check is ON Print out a warning , if -- DICT_TF_FORMAT_MAX < the tag, but -- innodb_file_format_check is off * The system tablespace tag is re-settable using: set innodb_file_format_check = <file_format> Approved by: Sunny
This commit is contained in:
parent
3bad6e2511
commit
fc02f76d78
10 changed files with 756 additions and 76 deletions
|
@ -115,36 +115,6 @@ static const long AUTOINC_OLD_STYLE_LOCKING = 0;
|
|||
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
|
||||
static const long AUTOINC_NO_LOCKING = 2;
|
||||
|
||||
/* List of animal names representing file format. */
|
||||
const char* file_format_name_map[] = {
|
||||
"Antelope",
|
||||
"Barracuda",
|
||||
"Cheetah",
|
||||
"Dragon",
|
||||
"Elk",
|
||||
"Fox",
|
||||
"Gazelle",
|
||||
"Hornet",
|
||||
"Impala",
|
||||
"Jaguar",
|
||||
"Kangaroo",
|
||||
"Leopard",
|
||||
"Moose",
|
||||
"Nautilus",
|
||||
"Ocelot",
|
||||
"Porpoise",
|
||||
"Quail",
|
||||
"Rabbit",
|
||||
"Shark",
|
||||
"Tiger",
|
||||
"Urchin",
|
||||
"Viper",
|
||||
"Whale",
|
||||
"Xenops",
|
||||
"Yak",
|
||||
"Zebra"
|
||||
};
|
||||
|
||||
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
|
||||
innobase_log_buffer_size,
|
||||
innobase_additional_mem_pool_size, innobase_file_io_threads,
|
||||
|
@ -160,6 +130,12 @@ static char* innobase_data_home_dir = NULL;
|
|||
static char* innobase_data_file_path = NULL;
|
||||
static char* innobase_log_group_home_dir = NULL;
|
||||
static char* innobase_file_format_name = NULL;
|
||||
|
||||
/* Note: This variable can be set to on/off and any of the supported
|
||||
file formats in the configuration file, but can only be set to any
|
||||
of the supported file formats during runtime. */
|
||||
static char* innobase_file_format_check = NULL;
|
||||
|
||||
/* The following has a misleading name: starting from 4.0.5, this also
|
||||
affects Windows: */
|
||||
static char* innobase_unix_file_flush_method = NULL;
|
||||
|
@ -218,18 +194,38 @@ static handler *innobase_create_handler(handlerton *hton,
|
|||
Validate the file format name and return its corresponding id. */
|
||||
static
|
||||
uint
|
||||
file_format_name_lookup(
|
||||
/*====================*/
|
||||
/* out: valid file format id*/
|
||||
const char* format_name); /* in: pointer to file format name */
|
||||
|
||||
innobase_file_format_name_lookup(
|
||||
/*=============================*/
|
||||
/* out: valid file format id */
|
||||
const char* format_name); /* in: pointer to file format
|
||||
name */
|
||||
/****************************************************************
|
||||
Validate the file format check config parameters, as a side affect it
|
||||
sets the srv_check_file_format_at_startup variable. */
|
||||
static
|
||||
bool
|
||||
innobase_file_format_check_on_off(
|
||||
/*==============================*/
|
||||
/* out: true if one of
|
||||
"on" or "off" */
|
||||
const char* format_check); /* in: parameter value */
|
||||
/****************************************************************
|
||||
Validate the file format check config parameters, as a side affect it
|
||||
sets the srv_check_file_format_at_startup variable. */
|
||||
static
|
||||
bool
|
||||
innobase_file_format_check_validate(
|
||||
/*================================*/
|
||||
/* out: true if valid
|
||||
config value */
|
||||
const char* format_check); /* in: parameter value */
|
||||
/*****************************************************************
|
||||
Check if it is a valid file format. This function is registered as
|
||||
a callback with MySQL. */
|
||||
static
|
||||
int
|
||||
innodb_file_format_check(
|
||||
/*=====================*/
|
||||
innodb_file_format_name_validate(
|
||||
/*=============================*/
|
||||
/* out: 0 for valid file
|
||||
format */
|
||||
THD* thd, /* in: thread handle */
|
||||
|
@ -238,24 +234,55 @@ innodb_file_format_check(
|
|||
void* save, /* out: immediate result
|
||||
for update function */
|
||||
struct st_mysql_value* value); /* in: incoming string */
|
||||
|
||||
/********************************************************************
|
||||
Update the global variable using the "saved" value. This functions is
|
||||
registered as a callback with MySQL. */
|
||||
Update the system variable innodb_file_format using the "saved"
|
||||
value. This function is registered as a callback with MySQL. */
|
||||
static
|
||||
bool
|
||||
innodb_file_format_update(
|
||||
/*======================*/
|
||||
/* out: should never
|
||||
fail since it is
|
||||
already validated */
|
||||
THD* thd, /* in: thread handle */
|
||||
struct st_mysql_sys_var* var, /* in: pointer to
|
||||
system variable */
|
||||
void* var_ptr, /* out: where the
|
||||
formal string goes */
|
||||
void* save); /* in: immediate result
|
||||
from check function */
|
||||
innodb_file_format_name_update(
|
||||
/*===========================*/
|
||||
/* out: should never
|
||||
fail since it is
|
||||
already validated */
|
||||
THD* thd, /* in: thread handle */
|
||||
struct st_mysql_sys_var* var, /* in: pointer to
|
||||
system variable */
|
||||
void* var_ptr,/* out: where the
|
||||
formal string goes */
|
||||
void* save); /* in: immediate result
|
||||
from check function */
|
||||
/*****************************************************************
|
||||
Check if it is a valid file format. This function is registered as
|
||||
a callback with MySQL. */
|
||||
static
|
||||
int
|
||||
innodb_file_format_check_validate(
|
||||
/*==============================*/
|
||||
/* out: 0 for valid file
|
||||
format */
|
||||
THD* thd, /* in: thread handle */
|
||||
struct st_mysql_sys_var* var, /* in: pointer to system
|
||||
variable */
|
||||
void* save, /* out: immediate result
|
||||
for update function */
|
||||
struct st_mysql_value* value); /* in: incoming string */
|
||||
/********************************************************************
|
||||
Update the system variable innodb_file_format_check using the "saved"
|
||||
value. This function is registered as a callback with MySQL. */
|
||||
static
|
||||
bool
|
||||
innodb_file_format_check_update(
|
||||
/*============================*/
|
||||
/* out: should never
|
||||
fail since it is
|
||||
already validated */
|
||||
THD* thd, /* in: thread handle */
|
||||
struct st_mysql_sys_var* var, /* in: pointer to
|
||||
system variable */
|
||||
void* var_ptr,/* out: where the
|
||||
formal string goes */
|
||||
void* save); /* in: immediate result
|
||||
from check function */
|
||||
|
||||
/********************************************************************
|
||||
Return alter table flags supported in an InnoDB database. */
|
||||
|
@ -1812,7 +1839,8 @@ innobase_init(
|
|||
/* Validate the file format by animal name */
|
||||
if (innobase_file_format_name != NULL) {
|
||||
|
||||
format_id = file_format_name_lookup(innobase_file_format_name);
|
||||
format_id = innobase_file_format_name_lookup(
|
||||
innobase_file_format_name);
|
||||
|
||||
if (format_id > DICT_TF_FORMAT_MAX) {
|
||||
|
||||
|
@ -1829,8 +1857,42 @@ innobase_init(
|
|||
}
|
||||
|
||||
srv_file_format = format_id;
|
||||
innobase_file_format_name =
|
||||
(char*) file_format_name_map[srv_file_format];
|
||||
|
||||
/* Given the type of innobase_file_format_name we have little
|
||||
choice but to cast away the constness from the returned name.
|
||||
innobase_file_format_name is used in the MySQL set variable
|
||||
interface and so can't be const. */
|
||||
|
||||
innobase_file_format_name =
|
||||
(char*) trx_sys_file_format_id_to_name(format_id);
|
||||
|
||||
/* Process innobase_file_format_check variable */
|
||||
ut_a(innobase_file_format_check != NULL);
|
||||
|
||||
/* As a side affect it will set srv_check_file_format_at_startup
|
||||
on valid input. First we check for "on"/"off". */
|
||||
if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
|
||||
|
||||
/* Did the user specify a format name that we support ?
|
||||
As a side affect it will update the variable
|
||||
srv_check_file_format_at_startup*/
|
||||
if (!innobase_file_format_check_validate(
|
||||
innobase_file_format_check)) {
|
||||
|
||||
sql_print_error("InnoDB: invalid "
|
||||
"innodb_file_format_check value: "
|
||||
"should be either 'on' or 'off' or "
|
||||
"any value up to %s or it's "
|
||||
"equivalent numeric id",
|
||||
trx_sys_file_format_id_to_name(
|
||||
DICT_TF_FORMAT_MAX));
|
||||
|
||||
my_free(internal_innobase_data_file_path,
|
||||
MYF(MY_ALLOW_ZERO_PTR));
|
||||
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------*/
|
||||
|
||||
|
@ -1921,6 +1983,9 @@ innobase_init(
|
|||
}
|
||||
#endif /* MYSQL_DYNAMIC_PLUGIN */
|
||||
|
||||
/* Get the current high water mark format. */
|
||||
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
error:
|
||||
DBUG_RETURN(TRUE);
|
||||
|
@ -2793,12 +2858,20 @@ retry:
|
|||
}
|
||||
}
|
||||
|
||||
stats.block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
|
||||
in query optimization */
|
||||
/* Index block size in InnoDB: used by MySQL in query optimization */
|
||||
stats.block_size = 16 * 1024;
|
||||
|
||||
/* Init table lock structure */
|
||||
thr_lock_data_init(&share->lock,&lock,(void*) 0);
|
||||
|
||||
if (prebuilt->table) {
|
||||
/* We update the highest file format in the system table
|
||||
space, if this table has higher file format setting. */
|
||||
|
||||
trx_sys_file_format_max_update(
|
||||
prebuilt->table->flags, &innobase_file_format_check);
|
||||
}
|
||||
|
||||
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
|
@ -5827,6 +5900,11 @@ ha_innobase::create(
|
|||
|
||||
DBUG_ASSERT(innobase_table != 0);
|
||||
|
||||
/* We update the highest file format in the system table
|
||||
space, if this table has a higher file format setting. */
|
||||
|
||||
trx_sys_file_format_max_update(flags, &innobase_file_format_check);
|
||||
|
||||
/* Note: We can't call update_thd() as prebuilt will not be
|
||||
setup at this stage and so we use thd. */
|
||||
|
||||
|
@ -8749,13 +8827,13 @@ ha_innobase::check_if_incompatible_data(
|
|||
Validate the file format name and return its corresponding id. */
|
||||
static
|
||||
uint
|
||||
file_format_name_lookup(
|
||||
/*====================*/
|
||||
innobase_file_format_name_lookup(
|
||||
/*=============================*/
|
||||
/* out: valid file format id*/
|
||||
const char* format_name) /* in: pointer to file format name */
|
||||
{
|
||||
uint format_id;
|
||||
char* endp;
|
||||
uint format_id;
|
||||
|
||||
ut_a(format_name != NULL);
|
||||
|
||||
|
@ -8776,7 +8854,7 @@ file_format_name_lookup(
|
|||
format_id++) {
|
||||
const char* name;
|
||||
|
||||
name = file_format_name_map[format_id];
|
||||
name = trx_sys_file_format_id_to_name(format_id);
|
||||
|
||||
if (!innobase_strcasecmp(format_name, name)) {
|
||||
|
||||
|
@ -8788,13 +8866,66 @@ file_format_name_lookup(
|
|||
return(DICT_TF_FORMAT_MAX + 1);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Validate the file format check value, is it one of "on" or "off",
|
||||
as a side affect it sets the srv_check_file_format_at_startup variable. */
|
||||
static
|
||||
bool
|
||||
innobase_file_format_check_on_off(
|
||||
/*==============================*/
|
||||
/* out: true if config value one
|
||||
of "on" or "off" */
|
||||
const char* format_check) /* in: parameter value */
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (!innobase_strcasecmp(format_check, "off")) {
|
||||
|
||||
/* Set the value to disable checking. */
|
||||
srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
|
||||
|
||||
} else if (!innobase_strcasecmp(format_check, "on")) {
|
||||
|
||||
/* Set the value to the lowest supported format. */
|
||||
srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Validate the file format check config parameters, as a side affect it
|
||||
sets the srv_check_file_format_at_startup variable. */
|
||||
static
|
||||
bool
|
||||
innobase_file_format_check_validate(
|
||||
/*================================*/
|
||||
/* out: true if valid config value */
|
||||
const char* format_check) /* in: parameter value */
|
||||
{
|
||||
uint format_id;
|
||||
bool ret = true;
|
||||
|
||||
format_id = innobase_file_format_name_lookup(format_check);
|
||||
|
||||
if (format_id < DICT_TF_FORMAT_MAX + 1) {
|
||||
srv_check_file_format_at_startup = format_id;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Check if it is a valid file format. This function is registered as
|
||||
a callback with MySQL. */
|
||||
static
|
||||
int
|
||||
innodb_file_format_check(
|
||||
/*=====================*/
|
||||
innodb_file_format_name_validate(
|
||||
/*=============================*/
|
||||
/* out: 0 for valid file
|
||||
format */
|
||||
THD* thd, /* in: thread handle */
|
||||
|
@ -8804,8 +8935,8 @@ innodb_file_format_check(
|
|||
for update function */
|
||||
struct st_mysql_value* value) /* in: incoming string */
|
||||
{
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
const char* file_format_input;
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
int len = sizeof(buff);
|
||||
|
||||
ut_a(save != NULL);
|
||||
|
@ -8814,10 +8945,10 @@ innodb_file_format_check(
|
|||
file_format_input = value->val_str(value, buff, &len);
|
||||
|
||||
if (file_format_input != NULL) {
|
||||
|
||||
uint format_id;
|
||||
|
||||
format_id = file_format_name_lookup(file_format_input);
|
||||
format_id = innobase_file_format_name_lookup(
|
||||
file_format_input);
|
||||
|
||||
if (format_id <= DICT_TF_FORMAT_MAX) {
|
||||
|
||||
|
@ -8830,12 +8961,12 @@ innodb_file_format_check(
|
|||
}
|
||||
|
||||
/********************************************************************
|
||||
Update the global variable using the "saved" value. This functions is
|
||||
registered as a callback with MySQL. */
|
||||
Update the system variable innodb_file_format using the "saved"
|
||||
value. This function is registered as a callback with MySQL. */
|
||||
static
|
||||
bool
|
||||
innodb_file_format_update(
|
||||
/*======================*/
|
||||
innodb_file_format_name_update(
|
||||
/*===========================*/
|
||||
/* out: should never
|
||||
fail since it is
|
||||
already validated */
|
||||
|
@ -8853,7 +8984,108 @@ innodb_file_format_update(
|
|||
|
||||
srv_file_format = *(uint*) save;
|
||||
|
||||
(*(char**) var_ptr) = (char*) file_format_name_map[srv_file_format];
|
||||
/* Given the type of var_ptr we have little choice but to cast
|
||||
away the constness from the returned name. */
|
||||
(*(char**) var_ptr) =
|
||||
(char*) trx_sys_file_format_id_to_name(srv_file_format);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Check if valid argument to innodb_file_format_check. This
|
||||
function is registered as a callback with MySQL. */
|
||||
static
|
||||
int
|
||||
innodb_file_format_check_validate(
|
||||
/*==============================*/
|
||||
/* out: 0 for valid file
|
||||
format */
|
||||
THD* thd, /* in: thread handle */
|
||||
struct st_mysql_sys_var* var, /* in: pointer to system
|
||||
variable */
|
||||
void* save, /* out: immediate result
|
||||
for update function */
|
||||
struct st_mysql_value* value) /* in: incoming string */
|
||||
{
|
||||
const char* file_format_input;
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
int len = sizeof(buff);
|
||||
|
||||
ut_a(save != NULL);
|
||||
ut_a(value != NULL);
|
||||
|
||||
file_format_input = value->val_str(value, buff, &len);
|
||||
|
||||
if (file_format_input != NULL) {
|
||||
|
||||
/* Check if user set on/off, we want to print a suitable
|
||||
message if they did so. */
|
||||
|
||||
if (innobase_file_format_check_on_off(file_format_input)) {
|
||||
sql_print_warning(
|
||||
"InnoDB: invalid innodb_file_format_check"
|
||||
"value; on/off can only be set at startup or "
|
||||
"in the configuration file");
|
||||
} else if (innobase_file_format_check_validate(
|
||||
file_format_input)) {
|
||||
|
||||
uint format_id;
|
||||
|
||||
format_id = innobase_file_format_name_lookup(
|
||||
file_format_input);
|
||||
|
||||
ut_a(format_id <= DICT_TF_FORMAT_MAX);
|
||||
|
||||
*(uint*) save = format_id;
|
||||
|
||||
return(0);
|
||||
|
||||
} else {
|
||||
sql_print_warning(
|
||||
"InnoDB: invalid innodb_file_format_check "
|
||||
"value; can be any format up to %s "
|
||||
"or it's equivalent numeric id",
|
||||
trx_sys_file_format_id_to_name(
|
||||
DICT_TF_FORMAT_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Update the system variable innodb_file_format_check using the "saved"
|
||||
value. This function is registered as a callback with MySQL. */
|
||||
static
|
||||
bool
|
||||
innodb_file_format_check_update(
|
||||
/*============================*/
|
||||
/* out: should never
|
||||
fail since it is
|
||||
already validated */
|
||||
THD* thd, /* in: thread handle */
|
||||
struct st_mysql_sys_var* var, /* in: pointer to
|
||||
system variable */
|
||||
void* var_ptr, /* out: where the
|
||||
formal string goes */
|
||||
void* save) /* in: immediate result
|
||||
from check function */
|
||||
{
|
||||
uint format_id;
|
||||
|
||||
ut_a(save != NULL);
|
||||
ut_a(var_ptr != NULL);
|
||||
|
||||
format_id = *(uint*) save;
|
||||
|
||||
/* Update the max format id in the system tablespace. */
|
||||
if (trx_sys_file_format_max_set(format_id, (char**) var_ptr)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" [Info] InnoDB: the file format in the system "
|
||||
"tablespace is now set to %s.\n", *(char**) var_ptr);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
@ -8912,8 +9144,15 @@ static MYSQL_SYSVAR_BOOL(file_per_table, srv_file_per_table,
|
|||
static MYSQL_SYSVAR_STR(file_format, innobase_file_format_name,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"File format to use for new tables in .ibd files.",
|
||||
(mysql_var_check_func) &innodb_file_format_check,
|
||||
(mysql_var_update_func) &innodb_file_format_update, "Antelope");
|
||||
(mysql_var_check_func) &innodb_file_format_name_validate,
|
||||
(mysql_var_update_func) &innodb_file_format_name_update, "Antelope");
|
||||
|
||||
static MYSQL_SYSVAR_STR(file_format_check, innobase_file_format_check,
|
||||
PLUGIN_VAR_OPCMDARG,
|
||||
"The highest file format in the tablespace.",
|
||||
(mysql_var_check_func) &innodb_file_format_check_validate,
|
||||
(mysql_var_update_func) &innodb_file_format_check_update,
|
||||
"on");
|
||||
|
||||
static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
|
||||
PLUGIN_VAR_OPCMDARG,
|
||||
|
@ -9097,6 +9336,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||
MYSQL_SYSVAR(file_io_threads),
|
||||
MYSQL_SYSVAR(file_per_table),
|
||||
MYSQL_SYSVAR(file_format),
|
||||
MYSQL_SYSVAR(file_format_check),
|
||||
MYSQL_SYSVAR(flush_log_at_trx_commit),
|
||||
MYSQL_SYSVAR(flush_method),
|
||||
MYSQL_SYSVAR(force_recovery),
|
||||
|
|
|
@ -61,7 +61,9 @@ extern char* srv_arch_dir;
|
|||
dictionary tables are in the system tablespace 0 */
|
||||
extern my_bool srv_file_per_table;
|
||||
/* The file format to use on new *.ibd files. */
|
||||
extern uint srv_file_format;
|
||||
extern ulint srv_file_format;
|
||||
/* Whether to check file format during startup.*/
|
||||
extern ulint srv_check_file_format_at_startup;
|
||||
/* Place locks to records only i.e. do not use next-key locking except
|
||||
on duplicate key checking and foreign key checking */
|
||||
extern ibool srv_locks_unsafe_for_binlog;
|
||||
|
|
|
@ -389,6 +389,8 @@ or row lock! */
|
|||
trx_i_s_cache_t::rw_lock */
|
||||
#define SYNC_TRX_I_S_LAST_READ 1900 /* Used for
|
||||
trx_i_s_cache_t::last_read_mutex */
|
||||
#define SYNC_FILE_FORMAT_TAG 1200 /* Used to serialize access to the
|
||||
file format tag */
|
||||
#define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve
|
||||
this in X-mode, implicit or backround
|
||||
operations purge, rollback, foreign
|
||||
|
|
|
@ -298,7 +298,59 @@ UNIV_INTERN
|
|||
void
|
||||
trx_sys_print_mysql_master_log_pos(void);
|
||||
/*====================================*/
|
||||
|
||||
/*********************************************************************
|
||||
Initializes the tablespace tag system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_file_format_init(void);
|
||||
/*==========================*/
|
||||
/*********************************************************************
|
||||
Closes the tablespace tag system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_file_format_close(void);
|
||||
/*===========================*/
|
||||
/*********************************************************************
|
||||
Get the name representation of the file format from its id. */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
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. */
|
||||
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 */
|
||||
/*********************************************************************
|
||||
Get the name representation of the file format from its id. */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
trx_sys_file_format_max_get(void);
|
||||
/*=============================*/
|
||||
/* out: pointer to the max format name */
|
||||
/*********************************************************************
|
||||
Check for the max file format tag stored on disk. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
trx_sys_file_format_max_check(
|
||||
/*==========================*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
ulint max_format_id); /* in: the max format id to check */
|
||||
/************************************************************************
|
||||
Update the file format tag in the tablespace to the max value. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
trx_sys_file_format_max_update(
|
||||
/*===========================*/
|
||||
/* out: TRUE if value updated */
|
||||
uint flags, /* in: flags of the table */
|
||||
char** name); /* out: max format name */
|
||||
/* The automatically created system rollback segment has this id */
|
||||
#define TRX_SYS_SYSTEM_RSEG_ID 0
|
||||
|
||||
|
@ -397,6 +449,15 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
|
|||
|
||||
#define TRX_SYS_DOUBLEWRITE_BLOCK_SIZE FSP_EXTENT_SIZE
|
||||
|
||||
/* The offset of the file format tag on the trx system header page */
|
||||
#define TRX_SYS_FILE_FORMAT_TAG (UNIV_PAGE_SIZE - 16)
|
||||
|
||||
/* We use these random constants to reduce the probability of reading
|
||||
garbage (from previous versions) that maps to an actual format id. We
|
||||
use these as bit masks at the time of reading and writing from/to disk. */
|
||||
#define TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW 3645922177UL
|
||||
#define TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_HIGH 2745987765UL
|
||||
|
||||
/* Doublewrite control struct */
|
||||
struct trx_doublewrite_struct{
|
||||
mutex_t mutex; /* mutex protecting the first_free field and
|
||||
|
|
|
@ -358,3 +358,36 @@ drop table t8, t9;
|
|||
set global innodb_file_per_table=0;
|
||||
set global innodb_file_format=Antelope;
|
||||
set innodb_strict_mode=0;
|
||||
set global innodb_file_per_table=on;
|
||||
set global innodb_file_format=`Barracuda`;
|
||||
set global innodb_file_format_check=`Antelope`;
|
||||
create table normal_table (
|
||||
c1 int
|
||||
) engine = innodb;
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Antelope
|
||||
create table zip_table (
|
||||
c1 int
|
||||
) engine = innodb key_block_size = 8;
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
set global innodb_file_format_check=`Antelope`;
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Antelope
|
||||
show table status;
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
set global innodb_file_format_check=`Cheetah`;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format_check=`on`;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format_check=`off`;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
drop table normal_table, zip_table;
|
||||
|
|
|
@ -270,3 +270,33 @@ drop table t8, t9;
|
|||
eval set global innodb_file_per_table=$per_table;
|
||||
eval set global innodb_file_format=$format;
|
||||
eval set innodb_strict_mode=$mode;
|
||||
#
|
||||
# Testing of tablespace tagging
|
||||
#
|
||||
-- disable_info
|
||||
set global innodb_file_per_table=on;
|
||||
set global innodb_file_format=`Barracuda`;
|
||||
set global innodb_file_format_check=`Antelope`;
|
||||
create table normal_table (
|
||||
c1 int
|
||||
) engine = innodb;
|
||||
select @@innodb_file_format_check;
|
||||
create table zip_table (
|
||||
c1 int
|
||||
) engine = innodb key_block_size = 8;
|
||||
select @@innodb_file_format_check;
|
||||
set global innodb_file_format_check=`Antelope`;
|
||||
select @@innodb_file_format_check;
|
||||
-- disable_result_log
|
||||
show table status;
|
||||
-- enable_result_log
|
||||
select @@innodb_file_format_check;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format_check=`Cheetah`;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format_check=`on`;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format_check=`off`;
|
||||
select @@innodb_file_format_check;
|
||||
drop table normal_table, zip_table;
|
||||
-- disable_result_log
|
||||
|
|
|
@ -89,7 +89,12 @@ UNIV_INTERN char* srv_arch_dir = NULL;
|
|||
dictionary tables are in the system tablespace 0 */
|
||||
UNIV_INTERN my_bool srv_file_per_table;
|
||||
/* The file format to use on new *.ibd files. */
|
||||
UNIV_INTERN uint srv_file_format = 0;
|
||||
UNIV_INTERN ulint srv_file_format = 0;
|
||||
/* Whether to check file format during startup a value of
|
||||
DICT_TF_FORMAT_MAX + 1 means no checking ie. FALSE. The default is to
|
||||
set it to the highest format we support. */
|
||||
UNIV_INTERN ulint srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX;
|
||||
|
||||
#if DICT_TF_FORMAT_51
|
||||
# error "DICT_TF_FORMAT_51 must be 0!"
|
||||
#endif
|
||||
|
|
|
@ -1408,6 +1408,8 @@ innobase_start_or_create_for_mysql(void)
|
|||
mutex_exit(&(log_sys->mutex));
|
||||
}
|
||||
|
||||
trx_sys_file_format_init();
|
||||
|
||||
if (create_new_db) {
|
||||
mtr_start(&mtr);
|
||||
fsp_header_init(0, sum_of_new_sizes, &mtr);
|
||||
|
@ -1444,6 +1446,16 @@ innobase_start_or_create_for_mysql(void)
|
|||
recv_recovery_from_archive_finish();
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
} else {
|
||||
|
||||
/* Check if we support the max format that is stamped
|
||||
on the system tablespace. */
|
||||
err = trx_sys_file_format_max_check(
|
||||
srv_check_file_format_at_startup);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
return(err);
|
||||
}
|
||||
|
||||
/* We always try to do a recovery, even if the database had
|
||||
been shut down normally: this is the normal startup path */
|
||||
|
||||
|
@ -1873,6 +1885,8 @@ innobase_shutdown_for_mysql(void)
|
|||
srv_misc_tmpfile = 0;
|
||||
}
|
||||
|
||||
trx_sys_file_format_close();
|
||||
|
||||
mutex_free(&srv_monitor_file_mutex);
|
||||
mutex_free(&srv_dict_tmpfile_mutex);
|
||||
mutex_free(&srv_misc_tmpfile_mutex);
|
||||
|
|
|
@ -1055,6 +1055,7 @@ sync_thread_add_level(
|
|||
case SYNC_THR_LOCAL:
|
||||
case SYNC_ANY_LATCH:
|
||||
case SYNC_TRX_SYS_HEADER:
|
||||
case SYNC_FILE_FORMAT_TAG:
|
||||
case SYNC_DOUBLEWRITE:
|
||||
case SYNC_BUF_POOL:
|
||||
case SYNC_SEARCH_SYS:
|
||||
|
|
292
trx/trx0sys.c
292
trx/trx0sys.c
|
@ -22,6 +22,17 @@ Created 3/26/1996 Heikki Tuuri
|
|||
#include "log0log.h"
|
||||
#include "os0file.h"
|
||||
|
||||
/* The file format tag structure with id and name. */
|
||||
struct file_format_struct{
|
||||
uint id; /* id of the file format */
|
||||
const char* name; /* text representation of the
|
||||
file format */
|
||||
mutex_t mutex; /* covers changes to the above
|
||||
fields */
|
||||
};
|
||||
|
||||
typedef struct file_format_struct file_format_t;
|
||||
|
||||
/* The transaction system */
|
||||
UNIV_INTERN trx_sys_t* trx_sys = NULL;
|
||||
UNIV_INTERN trx_doublewrite_t* trx_doublewrite = NULL;
|
||||
|
@ -53,6 +64,44 @@ InnoDB. */
|
|||
UNIV_INTERN char trx_sys_mysql_bin_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
|
||||
UNIV_INTERN ib_int64_t trx_sys_mysql_bin_log_pos = -1;
|
||||
|
||||
/* List of animal names representing file format. */
|
||||
static const char* file_format_name_map[] = {
|
||||
"Antelope",
|
||||
"Barracuda",
|
||||
"Cheetah",
|
||||
"Dragon",
|
||||
"Elk",
|
||||
"Fox",
|
||||
"Gazelle",
|
||||
"Hornet",
|
||||
"Impala",
|
||||
"Jaguar",
|
||||
"Kangaroo",
|
||||
"Leopard",
|
||||
"Moose",
|
||||
"Nautilus",
|
||||
"Ocelot",
|
||||
"Porpoise",
|
||||
"Quail",
|
||||
"Rabbit",
|
||||
"Shark",
|
||||
"Tiger",
|
||||
"Urchin",
|
||||
"Viper",
|
||||
"Whale",
|
||||
"Xenops",
|
||||
"Yak",
|
||||
"Zebra"
|
||||
};
|
||||
|
||||
/* The number of elements in the file format name array. */
|
||||
static const ulint FILE_FORMAT_NAME_N =
|
||||
sizeof(file_format_name_map) / sizeof(file_format_name_map[0]);
|
||||
|
||||
/* This is used to track the maximum file format id known to InnoDB. It's
|
||||
updated via SET GLOBAL innodb_file_format_check = 'x' or when we open
|
||||
or create a table. */
|
||||
static file_format_t file_format_max;
|
||||
|
||||
/********************************************************************
|
||||
Determines if a page number is located inside the doublewrite buffer. */
|
||||
|
@ -1008,3 +1057,246 @@ trx_sys_create(void)
|
|||
|
||||
trx_sys_init_at_db_start();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Update the file format tag. */
|
||||
static
|
||||
ibool
|
||||
trx_sys_file_format_max_write(
|
||||
/*==========================*/
|
||||
/* out: always TRUE */
|
||||
ulint format_id, /* in: file format id */
|
||||
char** name) /* out: max file format name, can
|
||||
be NULL */
|
||||
{
|
||||
mtr_t mtr;
|
||||
byte* ptr;
|
||||
buf_block_t* block;
|
||||
ulint tag_value_low;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
block = buf_page_get(
|
||||
TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
|
||||
|
||||
file_format_max.id = format_id;
|
||||
file_format_max.name = trx_sys_file_format_id_to_name(format_id);
|
||||
|
||||
ptr = buf_block_get_frame(block) + TRX_SYS_FILE_FORMAT_TAG;
|
||||
tag_value_low = format_id + TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW;
|
||||
|
||||
if (name) {
|
||||
*name = (char*) file_format_max.name;
|
||||
}
|
||||
|
||||
mlog_write_dulint(
|
||||
ptr,
|
||||
ut_dulint_create(TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_HIGH,
|
||||
tag_value_low),
|
||||
&mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Read the file format tag. */
|
||||
static
|
||||
ulint
|
||||
trx_sys_file_format_max_read(void)
|
||||
/*==============================*/
|
||||
/* out: the file format */
|
||||
{
|
||||
mtr_t mtr;
|
||||
const byte* ptr;
|
||||
const buf_block_t* block;
|
||||
ulint format_id;
|
||||
dulint file_format_id;
|
||||
|
||||
/* Since this is called during the startup phase it's safe to
|
||||
read the value without a covering mutex. */
|
||||
mtr_start(&mtr);
|
||||
|
||||
block = buf_page_get(
|
||||
TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
|
||||
|
||||
ptr = buf_block_get_frame(block) + TRX_SYS_FILE_FORMAT_TAG;
|
||||
file_format_id = mach_read_from_8(ptr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
format_id = file_format_id.low - TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return(format_id);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Get the name representation of the file format from its id. */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
trx_sys_file_format_id_to_name(
|
||||
/*===========================*/
|
||||
/* out: pointer to the name */
|
||||
const uint id) /* in: id of the file format */
|
||||
{
|
||||
ut_a(id < FILE_FORMAT_NAME_N);
|
||||
|
||||
return(file_format_name_map[id]);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Check for the max file format tag stored on disk. Note: If max_format_id
|
||||
is == DICT_TF_FORMAT_MAX + 1 then we only print a warning. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
trx_sys_file_format_max_check(
|
||||
/*==========================*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
ulint max_format_id) /* in: max format id to check */
|
||||
{
|
||||
ulint format_id;
|
||||
|
||||
/* Check the file format in the tablespace. Do not try to
|
||||
recover if the file format is not supported by the engine
|
||||
unless forced by the user. */
|
||||
format_id = trx_sys_file_format_max_read();
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: highest supported file format is %s.\n",
|
||||
trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
|
||||
|
||||
if (format_id > DICT_TF_FORMAT_MAX) {
|
||||
|
||||
ut_a(format_id < FILE_FORMAT_NAME_N);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: %s: the system tablespace is in a file "
|
||||
"format that this version doesn't support - %s\n",
|
||||
((max_format_id <= DICT_TF_FORMAT_MAX)
|
||||
? "Error" : "Warning"),
|
||||
trx_sys_file_format_id_to_name(format_id));
|
||||
|
||||
if (max_format_id <= DICT_TF_FORMAT_MAX) {
|
||||
return(DB_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
format_id = (format_id > max_format_id) ? format_id : max_format_id;
|
||||
|
||||
/* We don't need a mutex here, as this function should only
|
||||
be called once at start up. */
|
||||
file_format_max.id = format_id;
|
||||
file_format_max.name = trx_sys_file_format_id_to_name(format_id);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
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 format_id, /* in: file format id */
|
||||
char** name) /* out: max file format name */
|
||||
{
|
||||
ibool ret = FALSE;
|
||||
|
||||
ut_a(name);
|
||||
ut_a(format_id <= DICT_TF_FORMAT_MAX);
|
||||
|
||||
mutex_enter(&file_format_max.mutex);
|
||||
|
||||
/* Only update if not already same value. */
|
||||
if (format_id != file_format_max.id) {
|
||||
|
||||
ret = trx_sys_file_format_max_write(format_id, name);
|
||||
}
|
||||
|
||||
mutex_exit(&file_format_max.mutex);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Update the file format tag in the tablespace only if the given format id
|
||||
is greater than the known max id. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
trx_sys_file_format_max_update(
|
||||
/*===========================*/
|
||||
uint flags, /* in: flags of the table.*/
|
||||
char** name) /* out: max file format name */
|
||||
{
|
||||
ulint format_id;
|
||||
ibool ret = FALSE;
|
||||
|
||||
format_id = (flags & DICT_TF_FORMAT_MASK) >> DICT_TF_FORMAT_SHIFT;
|
||||
|
||||
ut_a(name);
|
||||
ut_a(file_format_max.name != NULL);
|
||||
ut_a(format_id <= DICT_TF_FORMAT_MAX);
|
||||
|
||||
mutex_enter(&file_format_max.mutex);
|
||||
|
||||
if (format_id > file_format_max.id) {
|
||||
|
||||
ret = trx_sys_file_format_max_write(format_id, name);
|
||||
}
|
||||
|
||||
mutex_exit(&file_format_max.mutex);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Get the name representation of the file format from its id. */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
trx_sys_file_format_max_get(void)
|
||||
/*=============================*/
|
||||
/* out: pointer to the max format name */
|
||||
{
|
||||
return(file_format_max.name);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Initializes the tablespace tag system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_file_format_init(void)
|
||||
/*==========================*/
|
||||
{
|
||||
mutex_create(&file_format_max.mutex, SYNC_FILE_FORMAT_TAG);
|
||||
|
||||
/* We don't need a mutex here, as this function should only
|
||||
be called once at start up. */
|
||||
file_format_max.id = DICT_TF_FORMAT_51;
|
||||
|
||||
file_format_max.name = trx_sys_file_format_id_to_name(
|
||||
file_format_max.id);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Closes the tablespace tag system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_file_format_close(void)
|
||||
/*===========================*/
|
||||
{
|
||||
/* Does nothing at the moment */
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue