一、数据库与 MySQL 概述
在正式开始学习 MySQL 之前,我们先厘清几个关键概念。数据库是用于组织、存储和管理数据的仓库,而数据库管理系统(DBMS)则是帮助用户创建、维护和使用数据库的软件。MySQL 就是目前最流行的开源关系型数据库管理系统之一。
关系型数据库把数据组织成一张张相互关联的表。每张表由行和列组成:一行表示一条记录,一列表示一个字段。例如,一张学生表可能包含学号、姓名、年龄和班级等字段,每行则对应一名学生。
MySQL 之所以被广泛使用,主要因为:
- 开源免费:社区版可以免费使用,适合学习和中小企业项目。
- 性能较高:读写速度快,能够满足大部分 Web 应用和后台系统的需求。
- 生态成熟:有大量文档、教程、管理工具和第三方框架支持。
- 语法标准:遵循 SQL 标准,学习后可以较容易地迁移到其他关系型数据库。
常见的 MySQL 应用场景包括网站用户系统、订单系统、商品管理、日志存储以及各类数据分析任务。即使现在出现了很多 NoSQL 数据库,MySQL 在很多业务流程中仍然是核心存储方案。
二、MySQL 的安装与连接
学习 MySQL 的第一步,是在本机或服务器上完成安装。根据操作系统不同,可以选择不同的安装方式。初学者推荐使用官方安装包,或者使用集成开发环境,例如 XAMPP、WampServer,这些工具会把 MySQL 和其他 Web 组件一起装好。
安装完成后,可以通过命令行连接到 MySQL 服务:
shell
mysql -u root -p
输入密码后即可进入 MySQL 客户端。如果刚刚安装且还没有设置密码,有些版本可以直接回车进入。为了安全和日常管理,通常需要先创建独立账号并设置密码:
sql
CREATE USER 'demo_user'@'localhost' IDENTIFIED BY 'Demo@123456';
GRANT ALL PRIVILEGES ON demo_db.* TO 'demo_user'@'localhost';
FLUSH PRIVILEGES;
对于习惯图形化操作的用户,也可以使用 Navicat、DBeaver、DataGrip 或 MySQL Workbench 等工具。图形工具适合查看表结构、导入导出数据和调试 SQL,不过命令行仍然是排查问题时的基本功。
三、数据库与数据表的基本操作
连接数据库后,我们需要先创建数据库,再在数据库中创建数据表。数据库相当于一个容器,用来存放一组相关的表。下面的语句创建一个名为 school 的数据库:
sql
CREATE DATABASE school DEFAULT CHARACTER SET utf8mb4;
这里指定了 utf8mb4 字符集。它是 utf8 的超集,能够正确存储表情符号和更多 Unicode 字符,因此现在更推荐使用它。
接下来进入该数据库:
sql
USE school;
然后创建学生表。建表时不仅需要指定列名,还要为每列选择合适的数据类型,并设置必要的约束:
sql
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '学生ID',
student_no VARCHAR(20) NOT NULL UNIQUE COMMENT '学号',
name VARCHAR(50) NOT NULL COMMENT '姓名',
gender ENUM('男', '女') DEFAULT '男' COMMENT '性别',
age TINYINT UNSIGNED COMMENT '年龄',
class_name VARCHAR(50) COMMENT '班级',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) COMMENT '学生表';
上面这个建表语句包含了主键、自增、非空、唯一、默认值等约束,这些都是日常开发中非常常用的配置。
四、MySQL 常见数据类型
选择合适的数据类型,既关系到存储空间,也关系到查询性能和数据准确性。MySQL 的数据类型主要分为三类:数值类型、字符串类型、日期时间类型。
4.1 数值类型
整数类型常用 TINYINT、INT、BIGINT 等。它们的主要区别是占用空间和表示范围不同:
| 类型 | 占用字节 | 大致范围 |
|---|---|---|
| TINYINT | 1 字节 | 有符号约 -128 到 127 |
| INT | 4 字节 | 约 -21 亿到 21 亿 |
| BIGINT | 8 字节 | 非常大的整数范围 |
对于年龄、状态标记等数值,使用 TINYINT 可以节省空间。对于自增主键,如果数据量可能很大,可以使用 BIGINT。
小数类型常见的有 DECIMAL 和 FLOAT、DOUBLE。需要精确计算的金额字段应使用 DECIMAL(M,D),其中 M 是总位数,D 是小数位数,例如 DECIMAL(10,2) 可以表示最多 8 位整数和 2 位小数。
4.2 字符串类型
最常用的字符串类型是 VARCHAR 和 CHAR。VARCHAR(n) 是变长字符串,最多存储 n 个字符,适合姓名、地址等长度变化较大的数据。CHAR(n) 是定长字符串,适合存储固定长度的编码。
长文本可以使用 TEXT。三种 TEXT 类型分别是 TINYTEXT、TEXT 和 LONGTEXT,存储容量依次增大。文章内容、评论、JSON 字符串等都可以视大小选择 TEXT 类型。
4.3 日期时间类型
常用日期时间类型包括 DATE、DATETIME 和 TIMESTAMP:
DATE:只存储年月日,格式为 YYYY-MM-DD。DATETIME:存储日期和时间,范围为 1000 年到 9999 年。TIMESTAMP:也存储日期和时间,但范围较窄,并且会受到时区设置影响。
一般情况下,记录创建时间和更新时间推荐使用 DATETIME,因为它范围更大、行为更直观。
五、SQL 语言基础与分类
SQL 是结构化查询语言,用来和关系型数据库交互。按照功能可以大致分为四类:
- DDL :数据定义语言,例如
CREATE、ALTER、DROP。 - DML :数据操作语言,例如
INSERT、UPDATE、DELETE。 - DQL :数据查询语言,主要是
SELECT。 - DCL :数据控制语言,例如
GRANT、REVOKE。
日常开发中使用最多的是 DML 和 DQL。理解这四类语句的职责,有助于在维护数据库时快速判断某个操作会影响结构还是只影响数据。
六、数据插入、更新与删除
创建好表之后,就可以向表中写入数据。插入数据使用 INSERT 语句:
sql
INSERT INTO student (student_no, name, gender, age, class_name)
VALUES ('20260001', '张三', '男', 18, '高一(1)班');
也可以一次插入多条数据:
sql
INSERT INTO student (student_no, name, gender, age, class_name) VALUES
('20260002', '李四', '男', 19, '高一(2)班'),
('20260003', '王五', '女', 18, '高一(1)班'),
('20260004', '赵六', '男', 20, '高一(3)班');
更新数据使用 UPDATE 语句。需要注意的是,更新和删除语句几乎必须搭配 WHERE 条件,否则会影响整张表:
sql
UPDATE student
SET age = 19, class_name = '高一(2)班'
WHERE student_no = '20260001';
删除数据使用 DELETE 语句:
sql
DELETE FROM student WHERE student_no = '20260004';
如果不小心执行了不带 WHERE 的更新或删除,可能会清空整张表的数据。因此在生产环境中执行这类语句前,建议先使用 SELECT 确认影响范围,必要时进行备份。
七、数据查询:SELECT 语句
SELECT 是使用频率最高的 SQL 语句。最基础的查询是查看表中的所有列:
sql
SELECT * FROM student;
一般建议显示列出需要的字段,避免 SELECT *,因为这样更清晰,也更容易维护:
sql
SELECT student_no, name, age, class_name FROM student;
7.1 条件查询 WHERE
通过 WHERE 可以筛选符合条件的记录。常用运算符包括 =、>、<、>=、<=、<>、LIKE、IN、BETWEEN 等。
sql
SELECT name, age
FROM student
WHERE age >= 18 AND class_name = '高一(1)班';
模糊查询使用 LIKE,其中 % 表示任意多个字符,_ 表示任意单个字符:
sql
SELECT name FROM student WHERE name LIKE '张%';
范围查询可以使用 BETWEEN ... AND ...:
sql
SELECT name, age FROM student WHERE age BETWEEN 18 AND 20;
7.2 排序 ORDER BY
ORDER BY 用于对结果排序,ASC 表示升序,DESC 表示降序:
sql
SELECT name, age FROM student ORDER BY age DESC;
7.3 分页 LIMIT
LIMIT 用于限制返回行数,常用于分页。例如查询第 2 页,每页 10 条数据:
sql
SELECT * FROM student ORDER BY id LIMIT 10 OFFSET 10;
其中 OFFSET 10 表示跳过前 10 条记录。也可以写成 LIMIT 10, 10,第一个数字是偏移量,第二个数字是返回行数。
7.4 聚合函数与分组
MySQL 提供 COUNT、SUM、AVG、MAX、MIN 等聚合函数。例如统计学生总数:
sql
SELECT COUNT(*) AS total FROM student;
GROUP BY 可以按某个字段分组统计。下面统计每个班级的学生人数:
sql
SELECT class_name, COUNT(*) AS student_count
FROM student
GROUP BY class_name
ORDER BY student_count DESC;
如果要对分组后的结果继续筛选,需要使用 HAVING 而不是 WHERE:
sql
SELECT class_name, COUNT(*) AS student_count
FROM student
GROUP BY class_name
HAVING student_count >= 2;
简单来说,WHERE 在分组前过滤行,HAVING 在分组后过滤聚合结果。
八、约束与数据完整性
约束用来保证数据符合业务规则。MySQL 中常用的约束有主键约束、外键约束、唯一约束、非空约束、默认值约束和检查约束。
- 主键约束 PRIMARY KEY:唯一标识表中的一行,不能为 NULL。
- 外键约束 FOREIGN KEY:保证子表引用父表中的记录有效。
- 唯一约束 UNIQUE:要求字段值在表中不能重复。
- 非空约束 NOT NULL:要求字段必须有值。
- 默认值约束 DEFAULT:当未提供值时使用默认值。
- 检查约束 CHECK:MySQL 8.0 及以上支持,用来限制字段取值范围。
下面创建班级表和学生表,并建立外键关系:
sql
CREATE TABLE class_info (
id INT PRIMARY KEY AUTO_INCREMENT,
class_name VARCHAR(50) NOT NULL UNIQUE
);
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
student_no VARCHAR(20) NOT NULL UNIQUE,
name VARCHAR(50) NOT NULL,
class_id INT,
CONSTRAINT fk_student_class FOREIGN KEY (class_id)
REFERENCES class_info(id)
);
外键约束能够在一定程度上避免出现"孤儿数据"。不过在高并发系统中,有些团队会选择在应用层维护引用关系,不使用数据库外键,以降低写入时的锁和校验开销。是否使用外键需要结合具体业务判断。
九、多表关联查询
关系型数据库的核心能力之一,就是可以把分散在不同表中的数据关联起来查询。常用的关联方式包括内连接、左连接和右连接。
内连接 INNER JOIN 只返回两表中满足关联条件的记录:
sql
SELECT s.student_no, s.name, c.class_name
FROM student s
INNER JOIN class_info c ON s.class_id = c.id;
左连接 LEFT JOIN 返回左表全部记录,即使右表没有匹配记录,也仍然保留左表内容,右表字段显示为 NULL:
sql
SELECT s.student_no, s.name, c.class_name
FROM student s
LEFT JOIN class_info c ON s.class_id = c.id;
右连接 RIGHT JOIN 则相反,返回右表全部记录。实际开发中,使用左连接的情况更多一些。为了避免字段名冲突,上面的语句给表设置了简短别名,这也是写复杂查询时的好习惯。
十、事务与 ACID 特性
事务是一组要么全部成功、要么全部失败的数据库操作。事务可以保证数据从一种一致状态转变为另一种一致状态。事务具有 ACID 四个特性:
- 原子性 Atomicity:事务中的操作要么全部执行,要么全部不执行。
- 一致性 Consistency:事务执行前后,数据都满足业务规则和约束。
- 隔离性 Isolation:多个事务并发执行时相互之间不会产生错误影响。
- 持久性 Durability:事务一旦提交,对数据的修改会永久保存。
一个典型场景是转账:从 A 账户扣款,再向 B 账户加款。两个操作必须放在同一个事务中:
sql
START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE account_id = 'A';
UPDATE account SET balance = balance + 100 WHERE account_id = 'B';
COMMIT;
如果中间某个操作失败,应当执行 ROLLBACK 回滚整个事务:
sql
START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE account_id = 'A';
UPDATE account SET balance = balance + 100 WHERE account_id = 'B';
ROLLBACK;
MySQL 的 InnoDB 存储引擎完整支持事务,也是 MySQL 5.5 之后的默认存储引擎。使用事务相关功能时,需要确保表是 InnoDB 引擎。
十一、索引与查询优化
索引是帮助数据库快速定位数据的数据结构。没有索引时,数据库可能需要扫描整张表来查找数据;有合适索引时,则可以直接定位到符合条件的记录。
创建普通索引:
sql
CREATE INDEX idx_student_name ON student(name);
创建唯一索引:
sql
CREATE UNIQUE INDEX uk_student_no ON student(student_no);
并不是索引越多越好。索引会占用额外存储空间,并且在插入、更新和删除数据时需要维护索引,可能降低写入性能。通常应该为以下字段创建索引:
- 经常出现在
WHERE条件中的字段。 - 经常用于
ORDER BY排序的字段。 - 经常用于表关联的外键字段。
- 需要保证唯一性的字段。
同时要注意避免对低区分度字段单独建索引,例如性别字段通常只有"男"和"女"两个值,单独建索引的实际帮助有限。分析查询性能时,可以在查询语句前加上 EXPLAIN 查看执行计划:
sql
EXPLAIN SELECT * FROM student WHERE name = '张三';
通过执行计划可以观察是否使用了索引、扫描行数多少以及连接方式是否合理。
十二、用户权限与安全管理
数据库安全从合理分配权限开始。应避免所有应用都使用 root 账号,更不建议把 root 账号暴露给不相关人员。可以为不同应用创建不同账号,并只授予必要权限。
创建只读账号:
sql
CREATE USER 'readonly_user'@'%' IDENTIFIED BY 'Readonly@123456';
GRANT SELECT ON school.* TO 'readonly_user'@'%';
FLUSH PRIVILEGES;
这里的 '%' 表示允许从任意主机连接。出于安全考虑,生产环境应尽量限制为具体 IP 或内网网段。如果不再需要某个账号,可以删除:
sql
DROP USER 'readonly_user'@'%';
此外,还应定期备份数据、及时升级 MySQL 版本、避免在代码中硬编码数据库密码,并控制服务器和数据库端口的访问范围。
十三、备份与恢复
数据备份是数据库运维中非常重要的一环。MySQL 自带逻辑备份工具 mysqldump。最简单的全库备份命令如下:
shell
mysqldump -u root -p school > school_backup.sql
恢复备份时,可以先创建目标数据库,再导入备份文件:
shell
mysql -u root -p school < school_backup.sql
对于数据量较大的系统,还可以使用物理备份工具,例如 Percona XtraBackup,或者借助云数据库提供的自动备份能力。无论使用什么工具,都应该定期演练恢复流程,确保备份文件真正可用。
十四、常见报错与排错思路
初学者经常会遇到一些典型问题,掌握排查思路比记住单个解决方案更重要。
- Access denied:通常是账号、密码或主机权限配置错误,确认账号是否存在、密码是否正确、授权主机是否包含当前连接来源。
- Table does not exist :可能是表名写错,或者没有先执行
USE database_name切换到对应数据库。 - Duplicate entry:向有唯一约束的字段插入了重复值,检查主键或唯一索引字段。
- Data too long:插入的数据长度超过字段定义长度,通常需要调整字段长度或校验输入内容。
- Foreign key constraint fails:插入或更新的外键值在父表中不存在,先确认关联记录是否已创建。
- Lock wait timeout exceeded:事务长时间持有锁导致等待超时,需要排查长时间未提交的事务。
遇到错误时,建议先完整阅读 MySQL 返回的错误信息,再结合项目中的业务上下文定位问题,而不是直接搜索并套用解决方案。
十五、学习路线与练习建议
掌握 MySQL 基础之后,建议按照以下路线继续深入学习:
- 熟练写出常用查询,包括条件筛选、排序、分组、聚合和分页。
- 理解表结构设计,练习为实际业务场景拆分表、设置主外键和索引。
- 掌握事务隔离级别,了解脏读、不可重复读和幻读的区别。
- 学习执行计划分析,尝试优化慢查询。
- 了解主从复制、读写分离和高可用架构的基本原理。
最好的学习方式是结合实际项目练习。可以自己设计一个简单的学生管理、博客或订单系统,把建库、建表、增删改查、关联查询、事务和索引全部用起来。只有真正在项目中使用过这些知识,才能理解它们各自解决的问题和价值。