文章介绍了关于mysql提示[Warning] Invalid table or database name,有需的朋友可参考一下.
- 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问题,通过查询和跟踪调试源码,有以下线索和处理方式.
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 函数,分两个线索继续查找.
线索一: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,观察数据库是否仍然出现该错误。
线索二: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(
- /*=======================*/
- dict_table_t* table, /*!< in, own: table definition
- (will be freed) */
- trx_t* trx) /*!< in: transaction handle */
该函数中调用了更深层次的函数,但从调试代码来看,暂时没有发现导致该问题的点.
处理方式:在线索一中的处理方式不能解决问题的情况下,再进行进一步的代码分析.
国外网站参考:
There is the presence of a bug in this case for two reasons:
- 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p1' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p2' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p3' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p4' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p5' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p6' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p7' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p8' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p9' 111116 10:48:29 [Warning] Invalid (old?) table or database name '#sql-3z8g_122a#P#p10' REASON #1 : Any table starting with #sql is a temp table. If these tables are still present in any database folder and the datetime stamp, simply delete them.
-
- REASON #2 : Look carefully at the suffix of each table. #P#p? resembles a partition tag. This would indicate an attempt to create a temp table using partitiions. That's sounds insane. There was bug report on this back in Feb 16, 2006 for MySQL 5.1.7-beta (closed Mar 15, 2006). The bug report is based on trying to do this manually. Is mysql attempting to do this internally ?
-
- IMHO I would upgrade mysql away from MySQL 5.1 up to MySQL 5.5
chinanx参考:
环境说明:
1. 错误记录在Percona MySQL 5.5.20版本中
2. 5.5版本的mysql为5.0的从库
错误日志如下:
- 120416 2:50:19 [Warning] Invalid (old?) table or database name '#sql1f58_a_340'
- 120416 2:50:19 [Warning] Invalid (old?) table or database name '#sql1f58_a_341'
级别为警告,没有发现其他异常,查看Percona 5.5.20的源代码sql/sql_table.cc:275-283行:
- if (res)
- {
-
- DBUG_PRINT("info", ("Error in explain_filename: %u", res));
- sql_print_warning("Invalid (old?) table or database name '%s'", from);
- DBUG_RETURN(my_snprintf(to, to_length,
- "<result %u when explaining filename '%s'>",
- res, from)); --phpfensi.com
- }
可以详细说明一下你计算临时表命名的公式吗?
以前推过,没有搞明白,下面是thread_id=297的手动创建的临时表的名字.
-rw-rw---- 1 mysql mysql 98304 Mar 24 18:28 #sqld0b_7_2.ibd
lz的这种临时很大可能是由于alter table的大表的生成的.
一般的alter都会导致表重建,如果表大,一般都会创建中间,就有点像你的那种临时文件,一直没有应用过对临时表进行alter,刚才测试了一下,也没有错误,不知道具体原因.
但是直接用create temporary table会有表结构的临时文件(*.frm等,名字不一样),也是放在/tmp下面的.出现问题之前有crash过吗?可以看一下mysql打开的临时文件中有没有这些warning中提示的:lsof -p mysql pid | grep /tmp
Warning] Invalid (old?) table or database name '#sql56c4_4f_48dc'
这个问题,又大规模出现了.在同一时间有:ALTER TABLE t1 ADD UNIQUE idx_id(id)
总结:经过以上代码调试和分析,得出两条线索,但是一直未能重现该问题,因此,目前只能对现有服务器进行线索一的处理。,如果按照线索一处理方式处理后,仍然出现该问题,将对第二步进行深入的分析. |