mysql的"[Warning] Invalid (old?) table or database name"问题
?
线上服务器出现[Warning] Invalid (old?) table or database name问题,通过分析binlog日志发现,在以下sql语句中出现问题,由于涉及敏感内容,用sql语法表示。
? ? ? ? DROP TABLE IF EXISTS [TEMP_TABLE_NAME];
? ? ? ? create temporary table [TEMP_TABLE_NAME] select col1,col2,... from [TABLE_NAME];
? ? ? ? alter table [TEMP_TABLE_NAME] add unique idx_col1(col1);
? ? ? ? 经过以上操作中,多次出现该warning问题。通过查询和跟踪调试
源码,有以下线索和处理方式: ?www.2cto.com ?
? ? ? ? mysql的"[Warning] Invalid (old?) table or database name"问题出现位置:
?
sql_table.cc:279
uint explain_filename (THD* thd, const char *from, char *to , uint to_length , enum_explain_filename_mode explain_mode )
?
? ? ? ? 跟踪代码发现,只有在ha_innodb.cc:1946的innobase_convert_identifier 中调用explain_filename函数。
/*****************************************************************//**
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
and quote it if needed.
@return ? ? ? pointer to the end of buf */
static char* innobase_convert_identifier (
/*========================*/
? ? ? ? ? ?char* ? ? ? ? ? buf, ? ? /*!< out: buffer for converted identifier */
? ? ? ? ? ?ulint ? ? ? ? ? ? buflen, ? ? ? ? ?/*!< in: length of buf, in bytes */
? ? ? ? ? ?const char * ?id, ? ? ? /*!< in: identifier to convert */
? ? ? ? ? ?ulint ? ? ? ? ? ? idlen, ? /*!< in: length of id, in bytes */
? ? ? ? ? ?void* ? ? ? ? ? thd, ? ? /*!< in: MySQL connection thread, or NULL */
? ? ? ? ? ?ibool ? ? ? ? ? ?file_id) /*!< in: TRUE=id is a table or database name;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FALSE=id is an UTF-8 string */
?
? ? ? ? 顺着线索向上查找,发现在有两个位置调用了innobase_convert_identifier 函数,分两个线索继续查找。 ?www.2cto.com ?
?
线索一:
ha_innodb.cc:2034
调用innodb_convert_identifier函数
/*****************************************************************//**
Convert a table or index name to the MySQL system_charset_info (UTF-8)
and quote it if needed.
@return ? ? ? pointer to the end of buf */
extern "C" UNIV_INTERN char* innobase_convert_name (
/*==================*/
? ? ? ? ? ?char* ? ? ? ? ? buf, ? ? /*!< out: buffer for converted identifier */
? ? ? ? ? ?ulint ? ? ? ? ? ? buflen, ? ? ? ? ?/*!< in: length of buf, in bytes */
? ? ? ? ? ?const char * ?id, ? ? ? /*!< in: identifier to convert */
? ? ? ? ? ?ulint ? ? ? ? ? ? idlen, ? /*!< in: length of id, in bytes */
? ? ? ? ? ?void* ? ? ? ? ? thd, ? ? /*!< in: MySQL connection thread, or NULL */
? ? ? ? ? ?ibool ? ? ? ? ? ?table_id) /*!< in: TRUE=id is a table or database name;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FALSE=id is an index name */
?
? ? ? ? 从函数定义和函数功能来看,该函数是将mysql的表名或者索引名转换成utf8,与字符集相关。查看现有
数据库字符集和生成的临时表字符集均为lanti1,推断是可能的原因之一。
处理方式:
? ? ? ? 修改数据库的字符集为utf8,观察数据库是否仍然出现该错误。
? www.2cto.com ?
线索二:
ha_innodb.cc:6269
调用innodb_convert_identifier函数
/*****************************************************************//**
Creates a table definition to an InnoDB database. */
static create_table_def (
/*=============*/
? ? ? ? ? ?trx_t* ? ? ? ? ?trx, ? ? ? ? ? ? ? /*!< in: InnoDB transaction handle */
? ? ? ? ? ?TABLE* ? ? ? ? ? ? ? ?form, ? ? ? ? ? /*!< in: information on table
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? columns and indexes */
? ? ? ? ? ?const char * ?table_name, ?/*!< in: table name */
? ? ? ? ? ?const char * ?path_of_temp_table, /*!< in: if this is a table explicitly
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? created by the user with the
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TEMPORARY keyword, then this
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? parameter is the dir path where the
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? table should be placed if we create
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? an .ibd file for it (no .ibd extension
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? in the path, though); otherwise this
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? is NULL */
? ? ? ? ? ?ulint ? ? ? ? ? ? flags) ? ? ? ? ? ?/*!< in: table flags */
?
? ? ? ? 在create_table_def 函数中,调用row_create_table_for_
mysql函数后,当返回值为DB_DUPLICATE_KEY时,调用innodb_convert_identifier,从而触发该warning。
?
row0mysql.c:1820
UNIV_INTERN int row_create_table_for_mysql(
/*===============