问题现象
访问、修改或删除名称包含大写字母的数据库出错,报错如下:
mysql> USE DB_2; ERROR 1049 (42000): Unknown database 'db_2' mysql> ALTER DATABASE DB_2 CHARACTER SET utf8mb3; ERROR 1 (HY000): Can't create/write to file './db_2/db.opt' (Errcode: 2 - No such file or directory) mysql> DROP DATABASE DB_2; ERROR 1008 (HY000): Can't drop database 'db_2'; database doesn't exist
访问、修改或删除名称包含大写字母的表出错,报错如下:
mysql> SELECT * FROM T1; ERROR 1146 (42S02): Table 'db_1.t1' doesn't exist mysql> ALTER TABLE T1 ENGINE = INNODB; ERROR 1146 (42S02): Table 'db_1.t1' doesn't exist mysql> DROP TABLE T1; ERROR 1051 (42S02): Unknown table 'db_1.t1'
MySQL 5.7升级8.0失败,错误日志中包含如下信息:
[ERROR] [MY-013520] [Server] Schema name 'DB_2' containing upper case characters is not allowed with lower_case_table_names = 1. [ERROR] [MY-013521] [Server] Table name 'db_1.T1' containing upper case characters is not allowed with lower_case_table_names = 1. [ERROR] [MY-010022] [Server] Failed to Populate DD tables. [ERROR] [MY-010119] [Server] Aborting
可能原因
数据库执行了lower_case_table_names
参数修改的操作。
参数介绍
参数lower_case_table_names
决定MySQL中库名与表名是否通过不区分大小写的方式进行存储。
取值说明:
0:库名和表名严格区分大小写存储,且访问时保留原大小写形式(区分大小写匹配)。
1:库名和表名强制转为小写存储,访问时需使用小写名称(不区分大小写匹配)。
2:库名和表名保留大小写存储,但访问时会自动转为小写(仅适用于某些文件系统,RDS MySQL不支持此取值)。
RDS MySQL实例限制:
仅支持取值0或1,不支持取值2。
版本差异:
MySQL 8.0以下版本:该参数为只读,可通过修改cnf文件并重启实例生效。
MySQL 8.0版本:参数值在实例初始化时固定,初始化完成后无法修改。
问题复现
在MySQL 8.0以下版本,若数据库曾修改过lower_case_table_names
参数,可能导致以下严重问题:
参数值从0改为1后库表不可访问
参数初始值为0(区分大小写存储)时,创建了包含大写字母的库名和表名:
mysql> SHOW GLOBAL VARIABLES LIKE "lower_case_table_names"; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | lower_case_table_names | 0 | +------------------------+-------+ 1 row in set (0.01 sec) mysql> CREATE DATABASE db_1; Query OK, 1 row affected (0.00 sec) mysql> USE db_1; Database changed # 创建包含大写字母的表名 mysql> CREATE TABLE T1(a int); Query OK, 0 rows affected (0.00 sec) # 创建包含大写字母的库名 mysql> CREATE DATABASE DB_2; Query OK, 1 row affected (0.00 sec)
修改参数为1(强制小写存储)后,系统无法正确识别原大小写混合的库表名,可能出现库表访问失败的情况:
mysql> SHOW GLOBAL VARIABLES LIKE "lower_case_table_names"; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | lower_case_table_names | 1 | +------------------------+-------+ 1 row in set (0.00 sec) mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | DB_2 | | db_1 | | mysql | | performance_schema | | sys | +--------------------+ 6 rows in set (0.00 sec) # 库名访问失败:DB_2 无法访问,切换、修改、删除 DB_2 失败 mysql> USE DB_2; ERROR 1049 (42000): Unknown database 'db_2' mysql> USE db_2; ERROR 1049 (42000): Unknown database 'db_2' mysql> ALTER DATABASE DB_2 CHARACTER SET utf8mb3; ERROR 1 (HY000): Can't create/write to file './db_2/db.opt' (Errcode: 2 - No such file or directory) mysql> ALTER DATABASE db_2 CHARACTER SET utf8mb3; ERROR 1 (HY000): Can't create/write to file './db_2/db.opt' (Errcode: 2 - No such file or directory) mysql> DROP DATABASE DB_2; ERROR 1008 (HY000): Can't drop database 'db_2'; database doesn't exist mysql> DROP DATABASE db_2; ERROR 1008 (HY000): Can't drop database 'db_2'; database doesn't exist mysql> USE db_1; Database changed mysql> SHOW TABLES; +----------------+ | Tables_in_db_1 | +----------------+ | T1 | +----------------+ 1 rows in set (0.00 sec) # 表名访问失败:T1 无法访问,查询、修改、删除 T1 失败 mysql> SELECT * FROM T1; ERROR 1146 (42S02): Table 'db_1.t1' doesn't exist mysql> SELECT * FROM t1; ERROR 1146 (42S02): Table 'db_1.t1' doesn't exist mysql> ALTER TABLE T1 ENGINE=INNODB; ERROR 1146 (42S02): Table 'db_1.t1' doesn't exist mysql> ALTER TABLE t1 ENGINE = INNODB; ERROR 1146 (42S02): Table 'db_1.t1' doesn't exist mysql> DROP TABLE T1; ERROR 1051 (42S02): Unknown table 'db_1.t1' mysql> DROP TABLE t1; ERROR 1051 (42S02): Unknown table 'db_1.t1'
大版本升级到MySQL 8.0失败
MySQL 5.7实例中存在大写库表名,且
lower_case_table_names = 1
,升级到MySQL 8.0时失败,错误日志示例:[ERROR] [MY-013520] [Server] Schema name 'DB_2' containing upper case characters is not allowed with lower_case_table_names = 1. [ERROR] [MY-013521] [Server] Table name 'db_1.T1' containing upper case characters is not allowed with lower_case_table_names = 1. [ERROR] [MY-010022] [Server] Failed to Populate DD tables. [ERROR] [MY-010119] [Server] Aborting
解决方案
当出现上述问题时,需要将lower_case_table_names
修改为0后才能正常访问、修改、删除库表和进行大版本升级。如果希望修改lower_case_table_names
为1,则需要先将所有包含大写字母的库、表名修改为小写形式。
为了避免因修改此参数导致的库表访问失败、大版本升级失败等问题,强烈建议MySQL 8.0 以下的版本在创建实例后不要对此参数进行修改。