MySQL常见面试题

存储引擎对比

  1. InnoDB中主键索引和数据放在一起,主键索引的B+树里放完整的数据行;MyISAM中索引和数据分开放,B树里存索引值和该行的物理地址
  2. InnoDB 支持 ACID 事务,MyISAM 不支持
  3. InnoDB支持行级锁,MyISAM 不支持

什么是页分裂

当向已满的索引页(通常是16KB)插入新数据时,存储引擎会将当前页分裂成两个页,以容纳新数据

这个过程涉及:分配新页、移动部分数据到新页、更新前后页的指针

页分裂会导致性能下降,因为它是相对昂贵的操作

对于纯粹的自增主键顺序写入,InnoDB确实会优先分配新页而非分裂现有页,这是自增主键性能优势的重要原因。但在实际生产环境中,由于并发等因素,仍可能发生少量页分裂。

为什么会发生?

每个节点(页)必须保持有序。在主键是非自增的情况下,我们必须保证后一个数据页中所有行的主键值比前一个数据页中的最大主键值要大。

填充因子(Fill Factor)

定义页的初始填充率(如 innodb_fill_factor=80 表示页只填充 80%)。

剩余空间用于后续插入,减少页分裂概率。

解决方案

1
2
3
4
5
CREATE TABLE orders (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,  -- 自增主键(聚簇索引)
  snowflake_id BIGINT UNIQUE,            -- 雪花ID作为业务唯一键
  ...
);

InnoDB的可重复读隔离级别下解决幻读

  1. 对于快照读(普通SELECT):通过MVCC,可重复读隔离级别,在事务第一次查询时创建ReadView

  2. 对于当前读(SELECT…FOR UPDATE/LOCK IN SHARE MODE/INSERT/UPDATE/DELETE):通过间隙锁和Next-Key Lock避免幻读。

SELECT * FROM t WHERE id > 100 FOR UPDATE会锁定id>100的所有间隙

其它问题

有一个索引字段b。b = 1 or b = 2 和b in(1,2)哪个执行效率高一点。

b in(1,2)更好

查询优化器在处理 b = 1 OR b = 2 时,它需要将这个查询条件拆分成两个独立的条件,也就是分别处理 b = 1 和 b = 2,然后再将这两个结果合并。

一个字段是 string 类型,有索引,现在在 where 条件中,使用 int 类型的数字和字段做比较,能使用索引吗?如果字段是 int 查询条件是 string 呢?

不能;能