lower case table names in MySQL and Identifier Case Sensitivity
Identifier Case Sensitivity
In MySQL, databases correspond to directories within the data directory. Each table within a database corresponds to at least one file within the database directory (and possibly more, depending on the storage engine). Triggers also correspond to files. Consequently, the case sensitivity of the underlying operating system plays a part in the case sensitivity of database, table, and trigger names. This means such names are not case-sensitive in Windows, but are case-sensitive in most varieties of Unix. One notable exception is mac-OS, which is Unix-based but uses a default file system type (HFS+) that is not case-sensitive. However, mac-OS also supports UFS volumes, which are case-sensitive just as on any Unix. The lower_case_table_names system variable also affects how the server handles identifier case sensitivity, as described later in this section.
Recommendation: Use lower_case_table_names=1 on all systems.
Note
mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
NOTE: I am referring to MySQL version 5.7 but concept may be applicable to other versions also.
To get into more details about this, Please read: Identifier Case Sensitivity in MySQL
Now let me tell you the story 😊 , Why I wrote this article in the first place.
One day my colleague told me that he had restored a snapshot in AWS RDS (lower_case_table_names = 0) and the setting of lower_case_table_names in the parameter group is set to 1.
Then he admit that he is not able to do any operations on the restored table, as he is getting table does not exist error or similar kind of. He was even not able to drop the database.
So, the end goal of this article is that I will explain why all it was happening when an RDS is restored as per circumstances mentioned above.
As far as I know, AWS RDS uses UNIX like OS and that is case sensitive.
Now lets talk about lower_case_table_names system variable in detail.
First straight from the MySQL documentation and then I will try to express it in a diagram form as per my knowledge and understanding of it.
Diagram Courtesy
How table and database names are stored on disk and used in MySQL is affected by the lower_case_table_names system variable, which you can set when starting mysqld. lower_case_table_names can take the values shown in the following table. This variable does not affect case sensitivity of trigger identifiers. On Unix, the default value of lower_case_table_names is 0. On Windows, the default value is 1. On mac-OS, the default value is 2.
Now, let me explain what happens when a snapshot (with parameter group whose lower_case_table_names=0) is restored as a MySQL RDS server with parameter group whose lower_case_table_names=1.
Solution
If you are using MySQL on only one platform, you do not normally have to change the lower_case_table_names variable from its default value. However, you may encounter difficulties if you want to transfer tables between platforms that differ in file system case sensitivity. For example, on Unix, you can have two different tables named my_table and MY_TABLE, but on Windows these two names are considered identical.
To avoid data transfer problems arising from lettercase of database or table names, you have two options:
- Use lower_case_table_names=1 on all systems. The main disadvantage with this is that when you use SHOW TABLES or SHOW DATABASES, you do not see the names in their original lettercase.
- Use lower_case_table_names=0 on Unix and lower_case_table_names=2 on Windows. This preserves the lettercase of database and table names. The disadvantage of this is that you must ensure that your statements always refer to your database and table names with the correct lettercase on Windows. If you transfer your statements to Unix, where lettercase is significant, they do not work if the lettercase is incorrect.
Exception: If you are using InnoDB tables and you are trying to avoid these data transfer problems, you should set lower_case_table_names to 1 on all platforms to force names to be converted to lowercase.
If you plan to set the lower_case_table_names system variable to 1 on Unix, you must first convert your old database and table names to lowercase before stopping mysqld and restarting it with the new variable setting. To do this for an individual table, use RENAME TABLE:
To convert one or more entire databases, dump them before setting lower_case_table_names, then drop the databases, and reload them after setting lower_case_table_names.
- Use mysqldump to dump each database:
mysqldump --databases db1 > db1.sqlmysqldump --databases db2 > db2.sql
Do this for each database that must be recreated.
- Use DROP DATABASE to drop each database.
- Stop the server, set lower_case_table_names, and restart the server.
- Reload the dump file for each database. Because lower_case_table_names is set, each database and table name is converted to lowercase as it is re-created:
mysql < db1.sqlmysql < db2.sql
Object names may be considered duplicates if their uppercase forms are equal according to a binary collation. That is true for names of cursors, conditions, procedures, functions, savepoints, stored routine parameters, stored program local variables, and plugins. It is not true for names of columns, constraints, databases, partitions, statements prepared with PREPARE, tables, triggers, users, and user-defined variables.
File system case sensitivity can affect searches in string columns of INFORMATION_SCHEMA tables.
Comments
Post a Comment