如果我们在 /var/lib/mysql 里新建一个文件夹,show databases; 查询时 MySQL 也会把这个文件夹识别成数据库;但我们一般不会这么做,所有库只用 create/drop database 语句管理,避免 MySQL 数据和磁盘文件不一致。
总结:
一个是MySQL层面的,一个是Linux文件系统层面的
MySQL 层面就是数据库的系统元数据登记,执行 create database db_name; 时,除了 Linux 在 /var/lib/mysql 生成对应文件夹 (文件系统层面),MySQL 还会在自身内置的系统数据表中记录这条库信息,包含库名、默认字符集、创建时间等配置,这就是 MySQL 逻辑层面。我们执行 show databases; 能查到这个库,本质就是 MySQL 读取自己保存的这份登记信息;执行 use db_name; 切换数据库,也是 MySQL 依靠这条记录定位到对应的逻辑空间。反过来执行 drop database db_name;,除了删掉磁盘文件夹,MySQL 同步删除系统表里这条库的登记记录,之后 show databases; 就不再显示该库。
这里我们说的 MySQL 整体就是服务端程序 (mysqld 后台进程),运行在 Linux 后台、监听端口、存磁盘数据、解析 SQL、管理 /var/lib/mysql 目录的 mysqld 程序 。而我们敲 mysql> 命令进入的黑框,是 MySQL 客户端,只负责输入 SQL 指令、把语句发给服务端,自身不存任何数据。当我们在客户端输入 create database xxx;,客户端把这条语句通过网络发给服务端进程,服务端一边在 Linux 的 /var/lib/mysql 建磁盘文件夹 (文件系统),一边在自己内部系统表登记库信息 (MySQL 逻辑层),两件事全是服务端完成。
查看当前库字符集使用 show variables like 'character_set_database';,如上,查询结果为 utf8mb4,这就是当前数据库用来存储字符数据的编码格式;
校验集
查看当前库校对集使用 show variables like 'collation_database';,对应配套校对集是 utf8mb4_unicode_ci,这个校对集依附 utf8mb4 字符集,用来负责字段对比、数据排序时的字符规则。
另外执行 show variables like 'collation_%'; 能够一次性查出全系统三处校对配置,分别是连接、当前库、服务全局的校对规则,当前环境里三项统一都是 utf8mb4_unicode_ci,全链路编码保持一致可以避免乱码问题。
此外我们还可以用 show charset; 语句查看所有的字符集:
在老版本 MySQL 里,两个库对应的磁盘目录中都会生成 db.opt 配置文件,打开文件就能查看,文件内会完整记录该库默认绑定的字符集与校验集。这两个库的字符集一致,存储数据的编码格式没有区别,但检验规则不同直接影响数据对比和排序逻辑,utf8mb4_unicode_ci 在字段匹配、排序时不区分英文字母大小写,而 utf8mb4_bin 会严格区分大小写。
下面我们建表:
我们先进入 test1 数据库,执行 create table if not exists person(name varchar(20)); 建立 person 表,用 show tables; 可以查到建好的表,desc person; 能够查看表字段结构,随后逐条执行 insert 语句,往表里插入 a、b、A、B、c、D 六条大小写不同的数据,数据落地存储使用数据库配置的字符集编码。
执行 select * from person; 可以把全部六条数据完整查询出来。
接着执行 select * from person where name='a'; 进行条件检索,这条语句同时查出 a 和 A 两条数据,也就证明 test1 的 utf8_general_ci 校对规则在匹配字段时不区分英文字母大小写。
下面我们再在 test2 数据库中再做上面的操作:
同样创建 person 数据表,再逐条插入 a、A、b、B、c、C 六条数据,全量查询时六条数据也都正常存在磁盘中。
在 test2 里执行 select * from person where name='a';,最终结果只出现小写 a 一条数据,由此验证 test2 的 utf8_bin 校验规则严格区分大小写。
除此之外我们还可以对比排序:
我们继续通过 order by 排序语句验证两种校对规则带来的排序差异,先在 test2 库执行 select * from person order by name;,结果里大写 A、B、C 排在前面,小写 a、b、c 排在末尾,这是 utf8_bin 检验集的特点,大写字母二进制数值更小,优先靠前排列;随后切换到 test1 库再次执行相同的排序查询,数据变成 a 和 A 挨在一起、b 和 B 挨在一起的排布,因为 utf8_general_ci 不区分大小写,排序时把同一个字母的大小写视作同等字符。