文章介紹了關于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 */ --Vevb.com
- 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)
- {
- /* Better to give something back if we fail parsing, than nothing at all */
- 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)); --Vevb.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)
總結:經過以上代碼調試和分析,得出兩條線索,但是一直未能重現該問題,因此,目前只能對現有服務器進行線索一的處理。,如果按照線索一處理方式處理后,仍然出現該問題,將對第二步進行深入的分析.
新聞熱點
疑難解答