MySQL 日志文件

MySQL 日志文件有很多,包括:

  • 错误日志(error log):记录启动、运行、关闭过程,帮助定位问题
  • 慢查询日志(slow query log):记录执行时间超过 long_query_time 的 SQL,用于性能优化
  • 一般查询日志(general log):记录所有请求,无论是否执行成功
  • 二进制日志(bin log):记录 DDL 和 DML(不含 SELECT/SHOW),以事件形式保存在二进制文件中,用于主从复制和数据恢复

InnoDB 存储引擎特有的日志:

  • 重做日志(redo log):记录事务对数据页的物理修改,保证崩溃恢复(WAL 机制)
  • 回滚日志(undo log):记录事务修改前的旧值,用于回滚和 MVCC 读

binlog 和 redo log 有什么区别?

维度binlogredo log
层级Server 层,所有存储引擎InnoDB 引擎特有
内容逻辑日志(SQL 或行变更)物理日志(数据页修改)
写入时机事务提交时一次写入事务进行中持续写入
写入方式追加,不覆盖循环写,空间固定

二者配合实现崩溃安全 + 主从复制:redo log 保证本地崩溃恢复,binlog 保证跨节点数据同步。

count 统计对比

执行效果

  • count(*):统计所有行,不忽略 NULL
  • count(1):统计所有行,不忽略 NULL,与 count(*) 语义等价
  • count(列名):只统计该列非 NULL 的行

执行速度

  • 列名为主键时,count(列名)count(1) 差距不大
  • 列名非主键且无索引时,count(1) / count(*) 通常更快
  • 有主键时,count(主键) 最优
  • 单列表时,count(*) 最优

InnoDB 不维护精确行数元数据,count(*) 在大表上需要扫描索引或全表,应尽量走最小的二级索引。

索引

聚簇索引 vs 二级索引

InnoDB 表数据按主键顺序存储在聚簇索引(叶子节点存完整行)。二级索引叶子节点存主键值,查询需回表。

最左前缀原则

联合索引 (a, b, c) 可用于 aa,ba,b,c 的查询条件,不能跳过左侧列。

覆盖索引

查询列全部在索引中即可避免回表,如 SELECT id, name FROM user WHERE name = ?(name, id) 索引。

事务与隔离级别

级别脏读不可重复读幻读
READ UNCOMMITTED可能可能可能
READ COMMITTED不会可能可能
REPEATABLE READ(默认)不会不会可能*
SERIALIZABLE不会不会不会

*InnoDB 在 RR 级别通过 MVCC + 间隙锁(Gap Lock)在很大程度上避免幻读。

MVCC 简述

多版本并发控制:每行有隐藏列 trx_id 和回滚指针,Read View 判断版本可见性,实现非锁定读。undo log 构成版本链,支持一致性读和回滚。