MySQL大小写敏感导致的问题分析

MYSQL对大小写敏感

见字如面,见标题知内容。你有遇到过因为MYSQL对大小写敏感而被坑的体验吗?

之前看过阿里巴巴Java开发手册,在MySql建表规约里有看到:

【强制】表名、字段名必须使用小写字母或数字 , 禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。

说明: MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、 表名、字段名,都不允许出现任何大写字母,避免节外生枝。

正例: aliyun _ admin , rdc _ config , level 3_ name 反例: AliyunAdmin , rdcConfig , level 3 name

如果没有真正遇到过类似的问题,有时候干巴巴的看这些规约体会不深,理解起来似懂非懂,并且也只是死记硬背而已。

01 一个表字母大小故事

最近自己在鼓捣一个项目玩玩,在自己本机上开发和测试过程中一直没有问题,但是部署到Linux服务器上后,发现有报错,日志信息大概是:

MySQLSyntaxErrorException: Table 'kytu.tb_sutyHo' doesn't exist

出现了问题,有点郁闷,本地开发好好的,怎么部署服务器就不行了。有鬼……不过莫慌。看着错误提示很明显,不就是tb_sutyHo 表不存在吗!

①于是我不慌不忙打开nv(navicat),查看这个表在不在,一看还真在,数据库中显示的tb_sutyho ,不过h是小写;

②查看代码发现代码中还真把表名写成tb_sutyHo ,就一个h写成大写H了。

问题找到了,原来是不小心写SQL的时候没有写对表名,改一下表名就搞定了,功能也一切正常了。一般情况下故事到这里也就应该结束了?问题找到了,也修复了,万事大吉了,稍后就可以吃鸡了。

对于不会玩吃鸡的我,到这里并没有结束,找到问题和解决问题的确很重要,但是找到问题出现的根源更重要,这样就能在下次规避此类问题,作为一个程序员不要两次掉入一个坑里。

我在想这个问题,本地Window环境怎么就一直没有出现这个报错提示呢?非要等我部署服务器才出现,这到底是什么问题?(如果你对Mysql大小敏感很了解,以下内容可以跳过….)

于是就利用搜索引擎,发现Mysql中控制数据库名和表名的大小写敏感由参数lower_case_table_names控制。

在本机Window环境查看如下:

mysql> show variables like '%case%';
+------------------------+-------+
| Variable_name   | Value |
+------------------------+-------+
| lower_case_file_system | ON |
| lower_case_table_names | 1  |
+------------------------+-------+

在Linux服务器查看如下:

mysql> show variables like '%case%';
+------------------------+-------+
| Variable_name   | Value |
+------------------------+-------+
| lower_case_file_system | OFF |
| lower_case_table_names | 0  |
+------------------------+-------+

从上面的结果已经可以看出不同了,然而对这两个参数还没有感觉,不知道具体是什么意思。

在介绍lower_case_table_names的时候,顺便也说一下lower_case_file_system。

lowercasefile_system

此变量描述数据目录所在的文件系统上文件名的区分大小写。 OFF表示文件名区分大小写,ON表示它们不区分大小写。此变量是只读的,因为它反映了文件系统属性并设置它对文件系统没有影响。

lowercasetable_names

该参数为静态,可设置为0、1、2。

0 --大小写敏感。(Unix,Linux默认) 创建的库表将原样保存在磁盘上。如create database TeSt;将会创建一个TeSt的目录,create table AbCCC …将会原样生成AbCCC.frm。 SQL语句也会原样解析。

1 --大小写不敏感。(Windows默认) 创建的库表时,MySQL将所有的库表名转换成小写存储在磁盘上。 SQL语句同样会将库表名转换成小写。 如需要查询以前创建的Testtable(生成Testtable.frm文件),即便执行select * from Testtable,也会被转换成select * from testtable,致使报错表不存在。

2 --大小写不敏感(OS X默认) 创建的库表将原样保存在磁盘上。 但SQL语句将库表名转换成小写。

On Windows the default value is 1. On macOS, the default value is 2. On Linux, a value of 2 is not supported; the server forces the value to 0 instead.

在Windows上,默认值为1。在macOS上,默认值为2。在Linux上不支持值2;服务器强制该值为0。

并且官网也提示说:如果在数据目录驻留在不区分大小写的文件系统(例如Windows或macOS)上的系统上运行MySQL,则不应将lowercasetable_names设置为0。

我自己在我的window10环境尝试设置lower_case_table_names为0的时候,MySQL的服务怎么也启动不能,启动服务报错。windows系统对大小写不敏感,见下图:

注: 如果要修改lower_case_table_names这个值,windows下修改my.ini ,Linux下修改my.cnf配置文件,需要重启服务,具体操作可以自行上网找资料。

02 注意事项

修改lowercasetable_names导致的常见不良隐患: 如果在lower_case_table_names=0时,创建了含有大写字母的库表,改为lower_case_table_names=1后,则会无法被查到。

首先设置lower_case_table_names=0

CREATE TABLE `Student` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(25) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

show tables;
+----------------+
| Tables_in_aflyun |
+----------------+
| Student   |
+----------------+

再设置lower_case_table_names=1,执行查询,不管表名是大写还是小写,都提示表不存在。

mysql> select * from Student;
1146 - Table 'aflyun.Student' doesn't exist

mysql> select * from student;
1146 - Table 'aflyun.student' doesn't exist

解决方法:如果要将默认的lower_case_tables_name为0设置成1,需先将已经存在的库表名转换为小写。

针对仅表名存在大写字母的情况:

①、lower_case_tables_name=0时,执行rename table成小写。

②、设置lower_case_tables_name=1,重启生效。

针对库名存在大写字母的情况:

①、lower_case_tables_name=0时,使用mysqldump导出,并删除老的数据库。

②、设置lower_case_tables_name=1,重启生效。

③、导入数据至实例,此时包含大写字母的库名已转换为小写。

03 总结

有了踩坑的经验,对开头说的阿里Mysql规约理解更加深入了。操作系统不同导致大小写敏感不一致。我们在开发时,应该按大小写敏感的原则去开发,这样可以使开发的程序兼容不同的操作系统。因此,建议在开发测试环境下把lower_case_table_names的值设为0,便于在开发中就严格控制代码大小写敏感,提高代码的兼容和严谨。

(0)

相关推荐

  • 解决MySQl查询不区分大小写的方法讲解

    问题 最近,在用SSH框架完成一个实践项目时,碰到了一个莫名其妙的Bug困扰了我好久,最后终于解决,记录如下. 问题:同学在测试系统的时候突然发现,数据库保存的账户本来应该是admin,结果该同学用Admin账户居然登录成功了-- --EXM???这样也行?好吧,我还是查找这个Bug发生的原因吧.然后就是各种排查程序的过程,找来找去也没发现什么问题.终于想到,不用hql,自己写sql语句在数据库里面直接查询试试,结果果然发现了问题所在: select * from user where user

  • MySql查询不区分大小写解决方案(两种)

    当我们输入不管大小写都能查询到数据,例如:输入 aaa 或者aaA ,AAA都能查询同样的结果,说明查询条件对大小写不敏感. 解决方案一: 于是怀疑Mysql的问题.做个实验:直接使用客户端用sql查询数据库. 发现的确是大小不敏感 . 通过查询资料发现需要设置collate(校对) . collate规则: *_bin: 表示的是binary case sensitive collation,也就是说是区分大小写的  *_cs: case sensitive collation,区分大小写  

  • mysql表名忽略大小写配置方法详解

    linux下mysql默认是要区分表名大小写的.mysql是否区分大小写设置是由参数lower_case_table_names决定的,其中: 1)lower_case_table_names = 0  区分大小写(即对大小写不敏感),默认是这种设置.这样设置后,在mysql里创建的表名带不带大写字母都没有影响,都可以正常读出和被引用. 2)lower_case_table_names = 1  不区分大小写(即对大小写敏感).这样设置后,表名在硬盘上以小写保存,MySQL将所有表名转换为小写存

  • MySQL数据库大小写敏感的问题

    在MySQL中,数据库对应数据目录中的目录.数据库中的每个表至少对应数据库目录中的一个文件(也可能是多个,取决于存储引擎).因此,所使用操作系统的大小写敏感性决定了数据库名和表名的大小写敏感性.这说明在大多数Unix中数据库名和表名对大小写敏感,而在Windows中对大小写不敏感. 一个显著的例外情况是Mac OS X,它基于Unix但使用默认文件系统类型(HFS+),对大小写不敏感. 在windows下表名不区分大小写,所以在导入数据后,有可能所有表名均为小写,而再从win导入linux后,在

  • Linux系统MySQL忘记密码,重置密码,忽略表名、列名大小写的方法

    在linunx系统刚装的MySQL,忘记曾经设置的密码或者安装过程无法设置密码时,试图用常用的密码猜测,如:1,11,111,1111,11111,111111,123456,000000,1234321等等最简单的默认密码来试探,结果试遍了也不对,还是无法进入mysql.原因可能是你当初设置的密码比较复杂后来给忘了,更可能的原因是你安装过程中没允许设置密码,这样的密码一般是MySQL随机生成的一大串由大小写字母.数字和符号组合成的复杂密码.这样的密码不需要白费力去试探了,这就需要通过特殊的方式

  • 详解MySQL查询时区分字符串中字母大小写的方法

    如果你在mysql有唯一约束的列上插入两行值'A'和'a',Mysql会认为它是相同的,而在oracle中就不会.就是mysql默认的字段值不区分大小写?这点是比较令人头痛的事.直接使用客户端用sql查询数据库. 发现的确是大小不敏感 . 通过查询资料发现需要设置collate(校对) . collate规则: *_bin: 表示的是binary case sensitive collation,也就是说是区分大小写的 *_cs: case sensitive collation,区分大小写 *

  • MySQL中查询的有关英文字母大小写问题的分析

    mysql数据库在做查询时候,有时候是英文字母大小写敏感的,有时候又不是的,主要是由mysql的字符校验规则的设置决定的,通常默认是不支持的大小写字母敏感的.  1. 什么是字符集和校验规则? 字符集是一套符号和编码.校对规则是在字符集内用于比较字符的一套规则.任何一个给定的字符集至少有一个校对规则,它可能有几个校对规则.要想列出一个字符集的校对规则,使用SHOW COLLATION语句. 校对规则一般有这些特征: 两个不同的字符集不能有相同的校对规则.     每个字符集有一个默认校对规则.例

  • MySQL大小写敏感导致的问题分析

    MYSQL对大小写敏感 见字如面,见标题知内容.你有遇到过因为MYSQL对大小写敏感而被坑的体验吗? 之前看过阿里巴巴Java开发手册,在MySql建表规约里有看到: [强制]表名.字段名必须使用小写字母或数字 , 禁止出现数字开头,禁止两个下划线中间只 出现数字.数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑. 说明: MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写.因此,数据库名. 表名.字段名,都不允许出现任何大写字母,避免节

  • MySQL服务器 IO 100%的分析与优化方案

    前言 压力测试过程中,如果因为资源使用瓶颈等问题引发最直接性能问题是业务交易响应时间偏大,TPS逐渐降低等.而问题定位分析通常情况下,最优先排查的是监控服务器资源利用率,例如先用TOP 或者nmon等查看CPU.内存使用情况,然后在排查IO问题,例如网络IO.磁盘IO的问题. 如果是磁盘IO问题,一般问题是SQL语法问题.MYSQL参数配置问题.服务器自身硬件瓶颈导致IOPS吞吐率问题. 本文主要给大家介绍的是关于MySQL服务器 IO 100%的分析与优化方案,下面话不多说了,来一起看看详细的

  • MySQL大小写敏感的注意事项

    由于这个原因,在阿里巴巴规约中这样要求: [强制]表名.字段名必须使用小写字母或数字 , 禁止出现数字开头,禁止两个下划线中间只 出现数字.数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑. 因此,数据库名. 表名.字段名,都不允许出现任何大写字母,避免引起不必要的麻烦. MySQL的大小写敏感是由参数控制的 mysql大小写敏感配置相关的两个参数,lower_case_file_system 和 lower_case_table_names. 查看当前mysql的大小写

  • MySQL的主从复制原理详细分析

    目录 前言 一.主从复制概念 二.读写分离的概念 三.主库和从库 1. 主库 2. 从库 四.主从复制的流程 五.主从复制效果展示 前言 在实际生产环境中,如果对mysql数据库的读和写都在一台数据库服务器中操作,无论是在安全性.高可用性,还是高并发等各个方面都是不能满足实际需求的,一般要通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力. 一.主从复制概念 主从复制是MySQL提供的基本的技术,主从复制的流程:binlog二进制日志(除了查询其他的更改相关的操作都会记录在b

  • 总结12个MySQL慢查询的原因分析

    目录 1. SQL 没加索引 2. SQL 索引不生效 2.1 隐式的类型转换,索引失效 2.2 查询条件包含 or,可能导致索引失效 2.3. like 通配符可能导致索引失效 2.5 在索引列上使用 mysql 的内置函数 2.6 对索引进行列运算(如,+.-.*./), 索引不生效 2.7 索引字段上使用(!= 或者 < >),索引可能失效 2.8 索引字段上使用 is null, is not null,索引可能失效 2.9 左右连接,关联的字段编码格式不一样 2.10 优化器选错了索

  • 简析mysql字符集导致恢复数据库报错问题

    mysql字符集编码错误的导入数据会提示错误了,这个和插入数据一样如果保存的数据与mysql编码不一样那么肯定会出现导入乱码或插入数据丢失的问题,下面我们一起来看一个例子. <script>ec(2);</script> 恢复数据库报错:由于字符集问题,最原始的数据库默认编码是latin1,新备份的数据库的编码是utf8,因此导致恢复错误. [root@hk byrd]# /usr/local/mysql/bin/mysql -uroot -p'admin' t4x < /t

  • sql和MySQL的语句执行顺序分析

    今天遇到一个问题就是mysql中insert into 和update以及delete语句中能使用as别名吗?目前还在查看,但是在查阅资料时发现了一些有益的知识,给大家分享一下,就是关于sql以及MySQL语句执行顺序: sql和mysql执行顺序,发现内部机制是一样的.最大区别是在别名的引用上. 一.sql执行顺序 (1)from (2) on (3) join (4) where (5)group by(开始使用select中的别名,后面的语句中都可以使用) (6) avg,sum....

  • MySQL慢查询之pt-query-digest分析慢查询日志

    一.简介 pt-query-digest是用于分析mysql慢查询的一个工具,它可以分析binlog.General log.slowlog,也可以通过SHOWPROCESSLIST或者通过tcpdump抓取的MySQL协议数据来进行分析.可以把分析结果输出到文件中,分析过程是先对查询语句的条件进行参数化,然后对参数化以后的查询进行分组统计,统计出各查询的执行时间.次数.占比等,可以借助分析结果找出问题进行优化. 二.安装pt-query-digest 1.下载页面:https://www.pe

  • Mysql NULL导致的神坑

    比较运算符中使用NULL mysql> select 1>NULL; +--------+ | 1>NULL | +--------+ | NULL | +--------+ 1 row in set (0.00 sec) mysql> select 1<NULL; +--------+ | 1<NULL | +--------+ | NULL | +--------+ 1 row in set (0.00 sec) mysql> select 1<>

  • 详解监听MySQL的binlog日志工具分析:Canal

    Canal是阿里巴巴旗下的一款开源项目,利用Java开发.主要用途是基于MySQL数据库增量日志解析,提供增量数据订阅和消费,目前主要支持MySQL. GitHub地址:https://github.com/alibaba/canal 在介绍Canal内部原理之前,首先来了解一下MySQL Master/Slave同步原理: MySQL master启动binlog机制,将数据变更写入二进制日志(binary log, 其中记录叫做二进制日志事件binary log events,可以通过sho

随机推荐