mirror of
https://github.com/MariaDB/server.git
synced 2026-05-03 13:45:34 +02:00
Bug #11765438 58406:
ISSUES WITH COPYING PARTITIONED INNODB TABLES FROM LINUX TO WINDOWS This problem was already fixed in mysql-trunk as part of bug #11755924. I am backporting the fix to mysql-5.1.
This commit is contained in:
parent
7c7506ccc6
commit
020f3914a2
4 changed files with 244 additions and 22 deletions
|
|
@ -948,6 +948,19 @@ innobase_get_charset(
|
|||
return(thd_charset((THD*) mysql_thd));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Get the current setting of the lower_case_table_names global parameter from
|
||||
mysqld.cc. We do a dirty read because for one there is no synchronization
|
||||
object and secondly there is little harm in doing so even if we get a torn
|
||||
read.
|
||||
@return value of lower_case_table_names */
|
||||
ulint
|
||||
innobase_get_lower_case_table_names(void)
|
||||
/*=====================================*/
|
||||
{
|
||||
return(lower_case_table_names);
|
||||
}
|
||||
|
||||
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
|
||||
extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
|
||||
/*******************************************************************//**
|
||||
|
|
@ -2579,19 +2592,29 @@ ha_innobase::bas_ext() const
|
|||
return ha_innobase_exts;
|
||||
}
|
||||
|
||||
/** Always normalize table name to lower case on Windows */
|
||||
#ifdef __WIN__
|
||||
#define normalize_table_name(norm_name, name) \
|
||||
normalize_table_name_low(norm_name, name, TRUE)
|
||||
#else
|
||||
#define normalize_table_name(norm_name, name) \
|
||||
normalize_table_name_low(norm_name, name, FALSE)
|
||||
#endif /* __WIN__ */
|
||||
|
||||
/*********************************************************************
|
||||
Normalizes a table name string. A normalized name consists of the
|
||||
database name catenated to '/' and table name. An example:
|
||||
test/mytable. On Windows normalization puts both the database name and the
|
||||
table name always to lower case. */
|
||||
table name always to lower case if "set_lower_case" is set to TRUE. */
|
||||
static
|
||||
void
|
||||
normalize_table_name(
|
||||
/*=================*/
|
||||
normalize_table_name_low(
|
||||
/*=====================*/
|
||||
char* norm_name, /* out: normalized name as a
|
||||
null-terminated string */
|
||||
const char* name) /* in: table name string */
|
||||
const char* name, /* in: table name string */
|
||||
ibool set_lower_case) /* in: TRUE if we want to set
|
||||
name to lower case */
|
||||
{
|
||||
char* name_ptr;
|
||||
char* db_ptr;
|
||||
|
|
@ -2621,9 +2644,9 @@ normalize_table_name(
|
|||
|
||||
norm_name[name_ptr - db_ptr - 1] = '/';
|
||||
|
||||
#ifdef __WIN__
|
||||
innobase_casedn_str(norm_name);
|
||||
#endif
|
||||
if (set_lower_case) {
|
||||
innobase_casedn_str(norm_name);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
@ -2806,6 +2829,8 @@ ha_innobase::open(
|
|||
THD* thd;
|
||||
ulint retries = 0;
|
||||
char* is_part = NULL;
|
||||
ibool par_case_name_set = FALSE;
|
||||
char par_case_name[MAX_FULL_NAME_LEN + 1];
|
||||
|
||||
DBUG_ENTER("ha_innobase::open");
|
||||
|
||||
|
|
@ -2852,16 +2877,87 @@ ha_innobase::open(
|
|||
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
|
||||
at support issue https://support.mysql.com/view.php?id=21080
|
||||
for more details. */
|
||||
#ifdef __WIN__
|
||||
is_part = strstr(norm_name, "#p#");
|
||||
#else
|
||||
is_part = strstr(norm_name, "#P#");
|
||||
#endif /* __WIN__ */
|
||||
|
||||
retry:
|
||||
/* Get pointer to a table object in InnoDB dictionary cache */
|
||||
ib_table = dict_table_get(norm_name, TRUE);
|
||||
|
||||
|
||||
if (NULL == ib_table) {
|
||||
if (is_part && retries < 10) {
|
||||
++retries;
|
||||
os_thread_sleep(100000);
|
||||
goto retry;
|
||||
/* MySQL partition engine hard codes the file name
|
||||
separator as "#P#". The text case is fixed even if
|
||||
lower_case_table_names is set to 1 or 2. This is true
|
||||
for sub-partition names as well. InnoDB always
|
||||
normalises file names to lower case on Windows, this
|
||||
can potentially cause problems when copying/moving
|
||||
tables between platforms.
|
||||
|
||||
1) If boot against an installation from Windows
|
||||
platform, then its partition table name could
|
||||
be all be in lower case in system tables. So we
|
||||
will need to check lower case name when load table.
|
||||
|
||||
2) If we boot an installation from other case
|
||||
sensitive platform in Windows, we might need to
|
||||
check the existence of table name without lowering
|
||||
case them in the system table. */
|
||||
if (innobase_get_lower_case_table_names() == 1) {
|
||||
|
||||
if (!par_case_name_set) {
|
||||
#ifndef __WIN__
|
||||
/* Check for the table using lower
|
||||
case name, including the partition
|
||||
separator "P" */
|
||||
memcpy(par_case_name, norm_name,
|
||||
strlen(norm_name));
|
||||
par_case_name[strlen(norm_name)] = 0;
|
||||
innobase_casedn_str(par_case_name);
|
||||
#else
|
||||
/* On Windows platfrom, check
|
||||
whether there exists table name in
|
||||
system table whose name is
|
||||
not being normalized to lower case */
|
||||
normalize_table_name_low(
|
||||
par_case_name, name, FALSE);
|
||||
#endif
|
||||
par_case_name_set = TRUE;
|
||||
}
|
||||
|
||||
ib_table = dict_table_get(
|
||||
par_case_name, FALSE);
|
||||
}
|
||||
if (!ib_table) {
|
||||
++retries;
|
||||
os_thread_sleep(100000);
|
||||
goto retry;
|
||||
} else {
|
||||
#ifndef __WIN__
|
||||
sql_print_warning("Partition table %s opened "
|
||||
"after converting to lower "
|
||||
"case. The table may have "
|
||||
"been moved from a case "
|
||||
"in-sensitive file system. "
|
||||
"Please recreate table in "
|
||||
"the current file system\n",
|
||||
norm_name);
|
||||
#else
|
||||
sql_print_warning("Partition table %s opened "
|
||||
"after skipping the step to "
|
||||
"lower case the table name. "
|
||||
"The table may have been "
|
||||
"moved from a case sensitive "
|
||||
"file system. Please "
|
||||
"recreate table in the "
|
||||
"current file system\n",
|
||||
norm_name);
|
||||
#endif
|
||||
goto table_opened;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_part) {
|
||||
|
|
@ -2892,6 +2988,8 @@ retry:
|
|||
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
|
||||
}
|
||||
|
||||
table_opened:
|
||||
|
||||
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
|
||||
sql_print_error("MySQL is trying to open a table handle but "
|
||||
"the .ibd file for\ntable %s does not exist.\n"
|
||||
|
|
|
|||
|
|
@ -160,6 +160,24 @@ management to ensure correct alignment for doubles etc. */
|
|||
/* Maximum number of parallel threads in a parallelized operation */
|
||||
#define UNIV_MAX_PARALLELISM 32
|
||||
|
||||
/** The maximum length of a table name. This is the MySQL limit and is
|
||||
defined in mysql_com.h like NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN, the
|
||||
number does not include a terminating '\0'. InnoDB probably can handle
|
||||
longer names internally */
|
||||
#define MAX_TABLE_NAME_LEN 192
|
||||
|
||||
/** The maximum length of a database name. Like MAX_TABLE_NAME_LEN this is
|
||||
the MySQL's NAME_LEN, see check_and_convert_db_name(). */
|
||||
#define MAX_DATABASE_NAME_LEN MAX_TABLE_NAME_LEN
|
||||
|
||||
/** MAX_FULL_NAME_LEN defines the full name path including the
|
||||
database name and table name. In addition, 14 bytes is added for:
|
||||
2 for surrounding quotes around table name
|
||||
1 for the separating dot (.)
|
||||
9 for the #mysql50# prefix */
|
||||
#define MAX_FULL_NAME_LEN \
|
||||
(MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14)
|
||||
|
||||
/*
|
||||
UNIVERSAL TYPE DEFINITIONS
|
||||
==========================
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
2012-01-16 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Fix Bug#11765438: 58406: ISSUES WITH COPYING PARTITIONED INNODB
|
||||
TABLES FROM LINUX TO WINDOWS
|
||||
|
||||
2012-01-04 The InnoDB Team
|
||||
|
||||
* row/row0mysql.c:
|
||||
|
|
|
|||
|
|
@ -1038,6 +1038,20 @@ innobase_get_charset(
|
|||
return(thd_charset((THD*) mysql_thd));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Get the current setting of the lower_case_table_names global parameter from
|
||||
mysqld.cc. We do a dirty read because for one there is no synchronization
|
||||
object and secondly there is little harm in doing so even if we get a torn
|
||||
read.
|
||||
@return value of lower_case_table_names */
|
||||
ulint
|
||||
innobase_get_lower_case_table_names(void)
|
||||
/*=====================================*/
|
||||
{
|
||||
return(lower_case_table_names);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
Determines the current SQL statement.
|
||||
@return SQL statement string */
|
||||
|
|
@ -3008,18 +3022,29 @@ ha_innobase::primary_key_is_clustered()
|
|||
return(true);
|
||||
}
|
||||
|
||||
/** Always normalize table name to lower case on Windows */
|
||||
#ifdef __WIN__
|
||||
#define normalize_table_name(norm_name, name) \
|
||||
normalize_table_name_low(norm_name, name, TRUE)
|
||||
#else
|
||||
#define normalize_table_name(norm_name, name) \
|
||||
normalize_table_name_low(norm_name, name, FALSE)
|
||||
#endif /* __WIN__ */
|
||||
|
||||
/*****************************************************************//**
|
||||
Normalizes a table name string. A normalized name consists of the
|
||||
database name catenated to '/' and table name. An example:
|
||||
test/mytable. On Windows normalization puts both the database name and the
|
||||
table name always to lower case. */
|
||||
table name always to lower case if "set_lower_case" is set to TRUE. */
|
||||
static
|
||||
void
|
||||
normalize_table_name(
|
||||
/*=================*/
|
||||
normalize_table_name_low(
|
||||
/*=====================*/
|
||||
char* norm_name, /*!< out: normalized name as a
|
||||
null-terminated string */
|
||||
const char* name) /*!< in: table name string */
|
||||
const char* name, /*!< in: table name string */
|
||||
ibool set_lower_case) /*!< in: TRUE if we want to set
|
||||
name to lower case */
|
||||
{
|
||||
char* name_ptr;
|
||||
char* db_ptr;
|
||||
|
|
@ -3049,9 +3074,9 @@ normalize_table_name(
|
|||
|
||||
norm_name[name_ptr - db_ptr - 1] = '/';
|
||||
|
||||
#ifdef __WIN__
|
||||
innobase_casedn_str(norm_name);
|
||||
#endif
|
||||
if (set_lower_case) {
|
||||
innobase_casedn_str(norm_name);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
|
|
@ -3445,6 +3470,8 @@ ha_innobase::open(
|
|||
THD* thd;
|
||||
ulint retries = 0;
|
||||
char* is_part = NULL;
|
||||
ibool par_case_name_set = FALSE;
|
||||
char par_case_name[MAX_FULL_NAME_LEN + 1];
|
||||
|
||||
DBUG_ENTER("ha_innobase::open");
|
||||
|
||||
|
|
@ -3491,16 +3518,87 @@ ha_innobase::open(
|
|||
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
|
||||
at support issue https://support.mysql.com/view.php?id=21080
|
||||
for more details. */
|
||||
#ifdef __WIN__
|
||||
is_part = strstr(norm_name, "#p#");
|
||||
#else
|
||||
is_part = strstr(norm_name, "#P#");
|
||||
#endif /* __WIN__ */
|
||||
|
||||
retry:
|
||||
/* Get pointer to a table object in InnoDB dictionary cache */
|
||||
ib_table = dict_table_get(norm_name, TRUE);
|
||||
|
||||
|
||||
if (NULL == ib_table) {
|
||||
if (is_part && retries < 10) {
|
||||
++retries;
|
||||
os_thread_sleep(100000);
|
||||
goto retry;
|
||||
/* MySQL partition engine hard codes the file name
|
||||
separator as "#P#". The text case is fixed even if
|
||||
lower_case_table_names is set to 1 or 2. This is true
|
||||
for sub-partition names as well. InnoDB always
|
||||
normalises file names to lower case on Windows, this
|
||||
can potentially cause problems when copying/moving
|
||||
tables between platforms.
|
||||
|
||||
1) If boot against an installation from Windows
|
||||
platform, then its partition table name could
|
||||
be all be in lower case in system tables. So we
|
||||
will need to check lower case name when load table.
|
||||
|
||||
2) If we boot an installation from other case
|
||||
sensitive platform in Windows, we might need to
|
||||
check the existence of table name without lowering
|
||||
case them in the system table. */
|
||||
if (innobase_get_lower_case_table_names() == 1) {
|
||||
|
||||
if (!par_case_name_set) {
|
||||
#ifndef __WIN__
|
||||
/* Check for the table using lower
|
||||
case name, including the partition
|
||||
separator "P" */
|
||||
memcpy(par_case_name, norm_name,
|
||||
strlen(norm_name));
|
||||
par_case_name[strlen(norm_name)] = 0;
|
||||
innobase_casedn_str(par_case_name);
|
||||
#else
|
||||
/* On Windows platfrom, check
|
||||
whether there exists table name in
|
||||
system table whose name is
|
||||
not being normalized to lower case */
|
||||
normalize_table_name_low(
|
||||
par_case_name, name, FALSE);
|
||||
#endif
|
||||
par_case_name_set = TRUE;
|
||||
}
|
||||
|
||||
ib_table = dict_table_get(
|
||||
par_case_name, FALSE);
|
||||
}
|
||||
if (!ib_table) {
|
||||
++retries;
|
||||
os_thread_sleep(100000);
|
||||
goto retry;
|
||||
} else {
|
||||
#ifndef __WIN__
|
||||
sql_print_warning("Partition table %s opened "
|
||||
"after converting to lower "
|
||||
"case. The table may have "
|
||||
"been moved from a case "
|
||||
"in-sensitive file system. "
|
||||
"Please recreate table in "
|
||||
"the current file system\n",
|
||||
norm_name);
|
||||
#else
|
||||
sql_print_warning("Partition table %s opened "
|
||||
"after skipping the step to "
|
||||
"lower case the table name. "
|
||||
"The table may have been "
|
||||
"moved from a case sensitive "
|
||||
"file system. Please "
|
||||
"recreate table in the "
|
||||
"current file system\n",
|
||||
norm_name);
|
||||
#endif
|
||||
goto table_opened;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_part) {
|
||||
|
|
@ -3531,6 +3629,8 @@ retry:
|
|||
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
|
||||
}
|
||||
|
||||
table_opened:
|
||||
|
||||
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
|
||||
sql_print_error("MySQL is trying to open a table handle but "
|
||||
"the .ibd file for\ntable %s does not exist.\n"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue