上篇文章:MySQL数据库基础硬核解析:从 C/S 网络服务到磁盘文件与存储引擎
目录
[删除数据库:DROP 的级联风险](#删除数据库:DROP 的级联风险)
[备份数据库:mysqldump 的本质](#备份数据库:mysqldump 的本质)
[恢复数据库:source 与 -B 的区别](#恢复数据库:source 与 -B 的区别)
[查看连接情况:show processlist](#查看连接情况:show processlist)
前言
库不是简单的名字空间,而是数据规则的边界。
在 MySQL 中,数据库,也就是库,看起来像是一个逻辑容器。表创建在库中,数据保存在表中。但库并不只是"表的文件夹"。库还携带一些非常关键的默认规则,尤其是字符集和校验规则。
创建数据库时,经常会看到:
sql
CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
这里的 CHARACTER SET 决定未来数据用什么编码存储,COLLATE 决定字符串如何比较、排序。很多中文乱码、大小写比较异常、排序结果不符合预期的问题,本质都和字符集、校验规则有关。
创建数据库的完整语法
创建数据库的基本语法是:
sql
CREATE DATABASE [IF NOT EXISTS] db_name
[create_specification [, create_specification] ...];
create_specification:
[DEFAULT] CHARACTER SET charset_name
[DEFAULT] COLLATE collation_name
其中大写部分是 SQL 关键字,\[\] 表示可选项。IF NOT EXISTS 用来避免数据库已存在时报错。CHARACTER SET 指定数据库字符集,COLLATE 指定字符集对应的校验规则。
示例:
sql
CREATE DATABASE db1;
CREATE DATABASE db2 CHARSET=utf8;
CREATE DATABASE db3 CHARSET=utf8 COLLATE utf8_general_ci;
如果创建数据库时没有指定字符集和校验规则,MySQL 会使用系统默认配置。不同版本默认值可能不同,例如新版本中常见默认字符集是 utf8mb4,默认校验规则可能是 utf8mb4_0900_ai_ci。
字符集与校验规则:一个负责存,一个负责比
创建数据库时有两个容易混淆的概念:字符集和校验规则。
字符集决定数据如何编码和存储。例如中文可以使用 utf8mb4、gbk、gb18030 等字符集。字符集回答的问题是:这个字符怎么变成字节保存下来?
校验规则决定字符串如何比较和排序。例如 'a' 和 'A' 是否相等,中文如何排序,大小写是否敏感。校验规则回答的问题是:两个字符串比较时应该按什么规则判断大小和相等?
可以这样理解:
- 字符集:数据怎么存
- 校验规则:数据怎么比
查看当前数据库默认字符集:
cpp
mysql> show variables like 'character_set_database';
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| character_set_database | utf8mb4 |
+------------------------+---------+
1 row in set (0.01 sec)
查看当前数据库默认校验规则:
sql
mysql> show variables like 'collation_database';
+--------------------+--------------------+
| Variable_name | Value |
+--------------------+--------------------+
| collation_database | utf8mb4_0900_ai_ci |
+--------------------+--------------------+
1 row in set (0.00 sec)
查看连接、数据库、服务器层面的校验规则:
sql
mysql> show variables like 'collation_%';
+----------------------+--------------------+
| Variable_name | Value |
+----------------------+--------------------+
| collation_connection | utf8mb4_0900_ai_ci |
| collation_database | utf8mb4_0900_ai_ci |
| collation_server | utf8mb4_0900_ai_ci |
+----------------------+--------------------+
3 rows in set (0.00 sec)
查看 MySQL 支持的字符集:
sql
mysql> show charset;
+----------+---------------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| binary | Binary pseudo charset | binary | 1 |
| cp1250 | Windows Central European | cp1250_general_ci | 1 |
| cp1251 | Windows Cyrillic | cp1251_general_ci | 1 |
| cp1256 | Windows Arabic | cp1256_general_ci | 1 |
| cp1257 | Windows Baltic | cp1257_general_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| cp852 | DOS Central European | cp852_general_ci | 1 |
| cp866 | DOS Russian | cp866_general_ci | 1 |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 |
| euckr | EUC-KR Korean | euckr_korean_ci | 2 |
| gb18030 | China National Standard GB18030 | gb18030_chinese_ci | 4 |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
| geostd8 | GEOSTD8 Georgian | geostd8_general_ci | 1 |
| greek | ISO 8859-7 Greek | greek_general_ci | 1 |
| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |
| keybcs2 | DOS Kamenicky Czech-Slovak | keybcs2_general_ci | 1 |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 |
| koi8u | KOI8-U Ukrainian | koi8u_general_ci | 1 |
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
| macce | Mac Central European | macce_general_ci | 1 |
| macroman | Mac West European | macroman_general_ci | 1 |
| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 |
| swe7 | 7bit Swedish | swe7_swedish_ci | 1 |
| tis620 | TIS620 Thai | tis620_thai_ci | 1 |
| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |
| ujis | EUC-JP Japanese | ujis_japanese_ci | 3 |
| utf16 | UTF-16 Unicode | utf16_general_ci | 4 |
| utf16le | UTF-16LE Unicode | utf16le_general_ci | 4 |
| utf32 | UTF-32 Unicode | utf32_general_ci | 4 |
| utf8mb3 | UTF-8 Unicode | utf8mb3_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_0900_ai_ci | 4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)
查看 MySQL 支持的校验规则:
sql
SHOW COLLATION;
校验规则对查询的影响
校验规则不是装饰,它会直接影响查询结果。创建一个不区分大小写的数据库:
mysql> create database test1 collate utf8_general_ci;
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> use test1
Database changed
mysql> create table if not exists person (name varchar(20));
Query OK, 0 rows affected (0.04 sec)
mysql> show tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| person |
+-----------------+
1 row in set (0.00 sec)
mysql> desc person;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
1 row in set (0.01 sec)
mysql> insert into person values('a');
Query OK, 1 row affected (0.01 sec)
mysql> insert into person values('A');
Query OK, 1 row affected (0.01 sec)
mysql> insert into person values('b');
Query OK, 1 row affected (0.00 sec)
mysql> insert into person values('B');
Query OK, 1 row affected (0.00 sec)
mysql> select * from person;
+------+
| name |
+------+
| a |
| A |
| b |
| B |
+------+
4 rows in set (0.00 sec)
mysql> select * from person where name = 'a';
+------+
| name |
+------+
| a |
| A |
+------+
2 rows in set (0.00 sec)
在 utf8_general_ci 中,ci 表示 case insensitive,即大小写不敏感。因此结果会包含:a,A
也就是说,在这个校验规则下,MySQL 认为 'a' 和 'A' 在比较时相等。
再创建一个区分大小写的数据库:
sql
CREATE DATABASE test2 COLLATE utf8_bin;
USE test2;
CREATE TABLE person(name VARCHAR(20));
INSERT INTO person VALUES('a');
INSERT INTO person VALUES('A');
INSERT INTO person VALUES('b');
INSERT INTO person VALUES('B');
查询:
sql
SELECT * FROM person WHERE name = 'a';
在 utf8_bin 下,字符串按照二进制比较,大小写敏感,因此只会查出:a
这说明校验规则会直接影响 WHERE 条件判断。
校验规则对排序的影响
校验规则也会影响排序。在不区分大小写的规则下:
sql
mysql> use test1;
mysql> select * from person order by name;
+------+
| name |
+------+
| a |
| A |
| b |
| B |
+------+
在二进制大小写敏感规则下:
sql
mysql> use test2;
mysql> select * from person order by name;
+------+
| name |
+------+
| A |
| B |
| a |
| b |
+------+
因为二进制比较中,大写字母和小写字母的编码值不同。这个例子说明:校验规则不仅影响"是否相等",还影响"谁排在前面"。
在真实业务中,如果登录用户名、验证码、token 等字段需要严格区分大小写,校验规则就必须认真设计。否则可能出现用户输入 Admin 却匹配到 admin 的问题。
查看数据库与显示创建语句
查看当前 MySQL 中有哪些数据库:
sql
SHOW DATABASES;
查看某个数据库的创建语句:
mysql> show create database test1;
+----------+--------------------------------------------------------------------------------------------------+
| Database | Create Database |
+----------+--------------------------------------------------------------------------------------------------+
| test1 | CREATE DATABASE `test1` /*!40100 DEFAULT CHARACTER SET gbk */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+--------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
数据库名外面的反引号 `` 是为了防止数据库名刚好是关键字,或者包含特殊字符。/*!40100 ... */` 看起来像注释,但不是普通注释,它表示当 MySQL 版本大于等于 4.01.00 时执行里面的语句。这是 MySQL 为兼容不同版本设计的一种特殊语法。
MySQL 建议关键字使用大写,例如 CREATE DATABASE、SHOW DATABASES,但不是强制要求。SQL 关键字通常大小写不敏感,写大写是为了提高可读性。
修改数据库:修改字符集和校验规则
修改数据库主要是修改数据库默认字符集和校验规则。
语法:
sql
ALTER DATABASE db_name
[alter_specification [, alter_specification] ...];
alter_specification:
[DEFAULT] CHARACTER SET charset_name
[DEFAULT] COLLATE collation_name
示例:把 test1 改成 gbk 字符集和 gbk_chinese_ci 校验规则:
mysql> alter database test1 charset = gbk collate gbk_chinese_ci;
Query OK, 1 row affected (0.01 sec)
**注意:**修改数据库默认字符集,并不一定会自动重写所有已经存在的表和字段。数据库默认字符集主要影响后续新建表和字段。如果表或字段本身已经指定了字符集,则以更具体的定义为准。字符集问题在生产环境中非常敏感,修改前必须备份并确认影响范围。
删除数据库:DROP 的级联风险
删除数据库语法:
sql
DROP DATABASE [IF EXISTS] db_name;
执行删除后:
MySQL 内部看不到对应数据库
Linux 数据目录下对应数据库文件夹会被删除
库中的数据表会被级联删除
这是一条高危命令。删除库不是把名字从列表中移除,而是会删除该库下所有表和数据文件。生产环境中执行 DROP DATABASE 必须极其谨慎,通常需要权限隔离、备份、审批和二次确认。
备份数据库:mysqldump 的本质
MySQL 常用逻辑备份工具是 mysqldump。它不是直接复制底层数据文件,而是把库结构、表结构、数据内容导出成一组 SQL 语句。换句话说,备份文件中保存的是重建数据库所需的 SQL。
备份单个数据库:
sql
mysqldump -P3306 -u root -p -B 数据库名 > 数据库备份文件路径
示例:
sql
mysqldump -P3306 -u root -p123456 -B mytest > D:/mytest.sql
-B 表示备份数据库,会在导出的 SQL 中包含创建数据库、使用数据库等语句。打开 .sql 文件可以看到里面通常包含 CREATE DATABASE、USE、CREATE TABLE、INSERT 等语句。
备份某个数据库中的指定表:
sql
mysqldump -u root -p 数据库名 表名1 表名2 > D:/mytest.sql
同时备份多个数据库:
sql
mysqldump -u root -p -B 数据库名1 数据库名2 ... > 数据库存放路径
恢复数据库:source 与 -B 的区别
恢复备份可以在 MySQL 客户端中使用:
sql
SOURCE D:/mysql-5.7.22/mytest.sql;
如果备份时带了 -B 参数,备份文件里包含创建数据库和切换数据库的语句,恢复时相对省事。
如果备份时没有带 -B,备份文件可能只有建表和插入数据语句,不包含创建数据库和 USE 数据库。此时恢复前需要手动执行:
sql
CREATE DATABASE mytest;
USE mytest;
SOURCE D:/mytest.sql;
这就是 -B 的实际意义:它让备份文件更加完整,恢复时不容易因为忘记创建库或切换库而失败。
查看连接情况:show processlist
查看当前 MySQL 连接:
sql
SHOW PROCESSLIST;
结果类似:
sql
+----+------+-----------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+------+---------+------+-------+------------------+
| 2 | root | localhost | test | Sleep | 1386 | | NULL |
| 3 | root | localhost | NULL | Query | 0 | NULL | show processlist |
+----+------+-----------+------+---------+------+-------+------------------+
它可以告诉我们当前有哪些用户连接到 MySQL、来自哪个主机、使用哪个数据库、正在执行什么命令、执行了多久。这个命令在排查数据库变慢、连接异常、疑似入侵时非常有用。如果看到陌生用户、陌生主机、长时间执行的异常 SQL,就需要进一步排查。
SHOW PROCESSLIST 是数据库现场排查的基础命令之一。它不是只给 DBA 用,后端开发也应该掌握。
小结:库操作的核心不是命令,而是规则边界
数据库的创建、修改、删除、备份、恢复,看似都是简单命令,但背后涉及几个核心问题:字符集决定数据如何存储,校验规则决定字符串如何比较和排序,DROP DATABASE 会删除整个库的数据文件,mysqldump 本质是导出重建数据的 SQL,SHOW PROCESSLIST 能观察当前连接现场。
真正理解库操作,不是背 CREATE DATABASE 和 DROP DATABASE,而是知道:一个库定义了后续表和数据的默认规则,也对应着底层文件系统中的目录边界。对库的任何操作,都可能影响后续数据的存储方式、比较规则、恢复能力和安全边界。