MySQL 基础知识面试题
1. mysqldump 备份
mysqldump -u root -p —all-databases > backup.sql mysqldump -u root -p db_name > db_backup.sql
2. 恢复
mysql -u root -p < backup.sql
mysql -u root -p db_name < db_backup.sql
`
物理备份:
`ash
3. Percona XtraBackup(热备,不锁表)
xtrabackup —backup —target-dir=/backup/
xtrabackup —prepare —target-dir=/backup/
`
| 备份方式 | 优点 | 缺点 |
|---|---|---|
| mysqldump | 简单、可跨版本 | 大数据量慢 |
| XtraBackup | 快、热备、增量备份 | 需额外安装工具 |
| Binlog | 时间点恢复(PITR) | 需配合全量备份使用 |
3.1. 【延伸追问】
- 如何进行时间点恢复(Point-In-Time Recovery)?
- 备份的恢复演练应该多久做一次?
3.2. 【易错坑点】
- ❌ 只有备份没有验证(备份文件损坏等于没备份)
- ❌ 忽略 Binlog 的保留时间,导致无法 PITR
4. 索引不适合哪些场景?
4.1. 【题目】
索引在哪些场景下不适合使用?
4.2. 【参考答案】
- 数据量小的表:全表扫描比索引查询更快(MySQL 优化器会自动选择)
- 频繁更新的列:索引维护(B+ 树调整)开销大于查询收益
- 区分度低的列:如性别(男/女),扫描一半数据不如全表扫描
- 很少查询的列:索引占用空间,没有查询收益
- 长文本/二进制列:索引体积大且意义不大(可使用前缀索引)
4.3. 【延伸追问】
- 什么是区分度(Cardinality)?如何查看?
- 前缀索引如何设置合适的长度?
4.4. 【易错坑点】
- ❌ 为所有列都建立索引(严重降低写入性能)
- ❌ 忽略 MySQL 优化器可能不使用索引(即使有索引)
5. 脏读、不可重复读、幻读的解释
5.1. 【题目】
什么是脏读、不可重复读、幻读?
5.2. 【参考答案】
| 问题 | 现象 | 产生原因 | 隔离级别解决 |
|---|---|---|---|
| 脏读 | 事务 A 读到事务 B 未提交的数据 | 写操作未提交即被读取 | READ COMMITTED 及以上 |
| 不可重复读 | 同一事务内两次读取同一条记录返回不同数据 | 其他事务修改并提交了该记录 | REPEATABLE READ 及以上 |
| 幻读 | 同一事务内两次查询结果集数量不同(出现新行) | 其他事务插入/删除了记录 | SERIALIZABLE(或 InnoDB 的间隙锁解决) |
`sql
— 不可重复读示例
— 事务 A:
SELECT balance FROM accounts WHERE id = 1; — 返回 100
— 事务 B: UPDATE accounts SET balance = 200 WHERE id = 1; COMMIT;
— 事务 A:
SELECT balance FROM accounts WHERE id = 1; — 返回 200(不可重复读)
`
5.3. 【延伸追问】
- InnoDB 如何通过 MVCC + Gap Lock 解决幻读?
- 在 READ COMMITTED 级别下如何避免不可重复读?
5.4. 【易错坑点】
- ❌ 混淆不可重复读(同一条记录值变化)和幻读(结果集行数变化)
- ❌ 误以为 REPEATABLE READ 能完全避免幻读(InnoDB 的 Next-Key Lock 实际上解决的是「当前读」下的幻读)
6. SQL 约束有哪几种?
6.1. 【题目】
SQL 约束有哪几种?
6.2. 【参考答案】
| 约束 | 说明 | 示例 |
|---|---|---|
| NOT NULL | 字段值不能为 NULL | name VARCHAR(50) NOT NULL |
| UNIQUE | 字段值唯一,允许 NULL | email VARCHAR(100) UNIQUE |
| PRIMARY KEY | 唯一标识每行,不允许 NULL | id INT PRIMARY KEY |
| FOREIGN KEY | 引用另一张表的主键,保证引用完整性 | FOREIGN KEY (dept_id) REFERENCES dept(id) |
| CHECK | 字段值必须满足指定条件(MySQL 8.0.16+ 才真正生效) | age INT CHECK (age >= 0) |
| DEFAULT | 为字段指定默认值 | status INT DEFAULT 1 |
6.3. 【延伸追问】
- CHECK 约束在 MySQL 8.0 之前为什么无效?(解析时忽略,不报错但也不检查)
- FOREIGN KEY 对性能有什么影响?(每次插入/更新需检查引用表)
6.4. 【易错坑点】
- ❌ 误以为 MySQL 的 CHECK 约束一直有效(MySQL 8.0.16 前仅解析不执行)
- ❌ 忽略外键对写入性能的影响
7. UNION 和 UNION ALL 的区别
7.1. 【题目】
UNION 和 UNION ALL 有什么区别?
7.2. 【参考答案】
| 特性 | UNION | UNION ALL |
|---|---|---|
| 重复行 | 去重(自动 DEDUP) | 包含重复行 |
| 排序 | 会对结果排序(以去重) | 不排序 |
| 性能 | 较慢(需要额外排序去重) | 更快 |
| 内存 | 需要临时表去重 | 直接追加结果 |
`sql
— UNION 去重效率低
SELECT name FROM employees_2023
UNION
SELECT name FROM employees_2024;
— UNION ALL 效率高(确认无重复时使用)
SELECT name FROM employees_2023
UNION ALL
SELECT name FROM employees_2024;
`
7.3. 【延伸追问】
- UNION 的去重逻辑是什么?(对所有 SELECT 的列做 DISTINCT)
- 什么场景下应该用 UNION ALL 替代 UNION?
7.4. 【易错坑点】
- ❌ 随意使用 UNION 而不是 UNION ALL(导致不必要的去重排序开销)
- ❌ 误以为 UNION 不会对结果排序(实际上为去重会排序)
8. 子查询及其用途
8.1. 【题目】
解释子查询及其用途。
8.2. 【参考答案】
子查询是嵌套在其他 SQL 查询中的查询,可以返回标量值、单列集合或多列结果。
`sql
— 标量子查询(返回单个值)
SELECT name, (SELECT MAX(salary) FROM employees) AS max_salary FROM departments;
— 行子查询(WHERE 条件中使用)
SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);
— EXISTS 子查询
SELECT * FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);
— FROM 子句中的派生表
SELECT avg_order.total
FROM (SELECT customer_id, COUNT(*) as total FROM orders GROUP BY customer_id) avg_order;
`
用途:
- 在 WHERE 条件中比较聚合结果
- 检查数据的存在性(EXISTS / NOT EXISTS)
- 在 FROM 中作为派生表(临时结果集)
8.3. 【延伸追问】
- 子查询和 JOIN 的性能差异是什么?(子查询在某些场景下会产生临时表,性能低于 JOIN)
- 关联子查询(Correlated Subquery)和非关联子查询的区别?
8.4. 【易错坑点】
- ❌ 滥用子查询导致性能问题(可用 JOIN 优化时优先使用 JOIN)
- ❌ 忽略了 EXISTS 和 IN 子查询在某些场景下的性能差异
关联文档
- MySQL 复制原理与配置:主从复制原理详解
- MySQL binlog 保留时间与清理:Binlog 管理
- MySQL 高可用方案:高可用架构对比
- GTID 集合详解:GTID 复制原理
