mysql常见面试题
mysql常见面试题
1. 什么是关系型数据库?MySQL属于哪种数据库?
答:关系型数据库(RDBMS)是建立在关系模型基础上的数据库,它使用表(Table)来存储数据,表由行(Row)和列(Column)组成。数据之间可以存在各种关系(一对一、一对多、多对多)。MySQL是一种开源的关系型数据库管理系统(RDBMS)。
2. SQL有哪些主要类型?
答:主要分为四类:
DDL (数据定义语言):用于定义或修改数据库结构。如
CREATE
,ALTER
,DROP
,TRUNCATE
。DML (数据操作语言):用于对数据进行增删改查。如
SELECT
,INSERT
,UPDATE
,DELETE
。DCL (数据控制语言):用于控制数据库的访问权限。如
GRANT
,REVOKE
。TCL (事务控制语言):用于管理数据库中的事务。如
COMMIT
,ROLLBACK
,SAVEPOINT
。
3. CHAR
和 VARCHAR
有什么区别?
答:
| 特性 | CHAR | VARCHAR |
| :— | :— | :— |
| 长度 | 固定长度。定义时指定长度,不足的部分用空格填充。 | 可变长度。根据实际内容长度存储,再加1-2个字节记录长度。 |
| 存储空间 | 总是占用定义长度的空间(例如 CHAR(10)
总是占10个字符的空间)。 | 占用实际数据长度 + 长度标识的空间。 |
| 存取速度 | 由于长度固定,存取速度更快。 | 由于需要计算长度,存取速度稍慢。 |
| 适用场景 | 存储长度基本固定的数据,如MD5哈希值、身份证号、手机号等。 | 存储长度变化较大的数据,如文章标题、用户名、地址等。 |
4. INNER JOIN
、LEFT JOIN
、RIGHT JOIN
和 FULL JOIN
的区别?
答:
INNER JOIN(内连接):返回两个表中匹配的行。
LEFT JOIN(左连接):返回左表的所有行,以及右表中匹配的行。如果右表无匹配,则右表部分为NULL。
RIGHT JOIN(右连接):返回右表的所有行,以及左表中匹配的行。如果左表无匹配,则左表部分为NULL。
FULL JOIN(全外连接):返回左表和右表中的所有行。如果某一边没有匹配,另一边则为NULL。MySQL不直接支持FULL JOIN,但可以通过
LEFT JOIN UNION RIGHT JOIN
来模拟。
二、索引(核心考点)
5. 什么是索引?它的作用和优缺点是什么?
答:索引是一种数据结构(如B+Tree),帮助MySQL高效获取数据,类似于书的目录。
优点:
大大加快数据的检索速度(最主要优点)。
通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
加速表与表之间的连接。
缺点:
需要占用额外的磁盘空间。
会降低数据写入(INSERT/UPDATE/DELETE)的速度,因为索引也需要同时被维护。
6. MySQL的索引主要使用哪种数据结构?为什么?
答:主要使用 B+Tree。
- 为什么是B+Tree?
矮胖树,查询效率高:B+Tree是一个多路平衡查找树,层级很低(通常3-4层就能存储千万级数据),意味着磁盘I/O次数非常少(每次I/O读取一页)。
适合范围查询:所有数据都存储在叶子节点,并且叶子节点之间通过指针相连,范围查询只需要遍历链表即可,非常高效。
查询效率稳定:任何查询都需要从根节点走到叶子节点,查询路径长度相同,效率稳定。
7. 什么是聚簇索引和非聚簇索引?
答:
聚簇索引(Clustered Index):表数据本身就按索引结构存储。叶子节点直接存储整行数据。一张表只能有一个聚簇索引(通常就是主键索引)。InnoDB的表必须有聚簇索引。
非聚簇索引(Secondary Index,辅助索引):叶子节点存储的是主键的值(InnoDB)或指向数据行的物理地址(MyISAM)。查找到主键后,还需要回表查询(通过主键回到聚簇索引中查找完整数据行)。
8. 什么是回表查询和覆盖索引?
答:
回表查询:先通过非聚簇索引找到对应记录的主键值,再根据主键值到聚簇索引中查找完整行数据的过程。多了一次索引查找,性能较低。
覆盖索引:如果一个索引包含了(或覆盖了)查询语句所需要的所有字段,那么引擎就可以直接从这个索引的叶子节点得到结果,而无需回表。这能极大地提升性能。
例子:表
user
有索引idx_name_age (name, age)
。查询SELECT age FROM user WHERE name = '张三'
; 因为age
已经在idx_name_age
索引中了,所以无需回表。
9. 如何创建高效的索引?(索引优化策略)
答:
最左前缀原则:对于联合索引
(a, b, c)
,它可以用于查询a
,a,b
,a,b,c
,但不能用于查询b
或c
或b,c
(索引会失效)。避免在索引列上使用函数或计算:
WHERE YEAR(create_time) = 2023
会导致索引失效。应改为范围查询WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'
。选择区分度高的列建索引:区分度指索引列不同值的数量与总记录数的比值。比值越高,索引效率越好(如身份证号非常适合建索引,性别则不适合)。
使用覆盖索引,避免回表。
避免使用
SELECT *
,只取需要的字段,增加覆盖索引的可能性。
三、事务与锁(核心考点)
10. 什么是数据库事务?它的ACID特性是什么?
答:事务是数据库操作的最小工作单元,作为一个整体一起向系统提交,要么都执行,要么都不执行。
A - Atomicity (原子性):事务中的所有操作是一个不可分割的整体,要么全部成功,要么全部失败回滚。
C - Consistency (一致性):事务执行前后,数据库必须从一个一致性状态变换到另一个一致性状态(数据完整性不被破坏)。
I - Isolation (隔离性):并发事务之间相互隔离,不应互相干扰。
D - Durability (持久性):事务一旦提交,它对数据库的改变就是永久性的。
11. MySQL的隔离级别有哪些?分别解决了什么并发问题?
答:由低到高有四个级别:
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
| :— | :— | :— | :— |
| 读未提交 (Read Uncommitted) | ❌ 可能 | ❌ 可能 | ❌ 可能 |
| 读已提交 (Read Committed) | ✅ 避免 | ❌ 可能 | ❌ 可能 |
| 可重复读 (Repeatable Read) | ✅ 避免 | ✅ 避免 | ❌ 可能 |
| 串行化 (Serializable) | ✅ 避免 | ✅ 避免 | ✅ 避免 |
脏读:一个事务读到了另一个未提交事务修改的数据。
不可重复读:一个事务内,多次读取同一数据,结果不同(因为被其他已提交事务修改了)。
幻读:一个事务内,多次查询同一范围的数据,记录数不同(因为被其他已提交事务新增或删除了)。InnoDB在RR级别通过MVCC和间隙锁解决了幻读问题。
MySQL默认的隔离级别是可重复读 (Repeatable Read)。