一、基本知识
MySQL是轻量级(简单;架构简洁;启动快、配置简单、学习成本低)的关系型数据库。
默认的数据库引擎是InnoDB,支持事务、行锁、外键、崩溃恢复,适合高并发、高可靠性业务。
所谓的关系型数据库即数据存在一张张二维表里,行是记录,列是字段,表和表之间可以关联。
1、MySQL支持的基本数据类型
数值类型:int(整数)、bigint(长整数)、double/float、decimal(m,n)(精确小数)
字符串类型:varchar(n)(可变长度字符串)、char(n)(固定长度)、text(长文本)
日期类型:datetime(年月日时分秒)、timestamp(时间戳,自动更新时间)、date(年月日)
2、基础约束
-
**主键(PRIMARY KEY):**唯一标识一行,非空 + 唯一,一张表只能有一个主键
-
**唯一(UNIQUE):**列的值不能重复,允许 NULL
-
**非空(NOT NULL):**列不能存 NULL
-
**默认值(DEFAULT):**没插入值时用默认值
3、多表查询
-
内连接(INNER JOIN):只查两张表匹配上的数据
-
左连接(LEFT JOIN):以左表为准,右表没有显示 NULL
-
右连接(RIGHT JOIN):以右表为准
4、存储引擎
- InnoDB:MySQL 默认,支持事务、行锁、外键
- MyISAM:老引擎,不支持事务
二、索引
1. 索引数据结构B + 树
- B + 树:MySQL 索引唯一核心结构
✅ 叶子节点有序链表、范围查询快、IO 次数少
✅ 非叶子节点不存数据,只存键,树更矮
P:为什么InnoDB的索引使用B+树?
- 哈希虽然等值查询
where id=?极快 ,但不支持范围查询 、无法排序、会哈希冲突→ 所以不能做数据库通用索引 - 二叉查找树极端情况退化成链表,查询时间复杂度是 O (n)
- 红黑树树太高,IO 次数多,磁盘查询太慢
- B树节点存数据,范围查询仍要回溯
- B+树 是
- 矮胖树,IO 次数极少
- 只有叶子节点存数据,非叶子只存键
- 叶子节点用双向链表串联,既支持顺序遍历、范围查询、排序 ,也支持逆序查询、页分裂合并
- 范围查询、排序、分页极快
2. 聚簇索引 vs 非聚簇索引
-
聚簇索引 :主键索引,叶子节点存整行数据,一张表只有一个
-
二级索引 :叶子节点存主键值,查询需要回表
-
回表:通过二级索引找到主键,再通过主键查完整数据
-
覆盖索引 :查询的字段都在索引里,避免回表,性能提升极大
3. 最左匹配原则
联合索引 (a,b,c)
-
生效:
a、a,b、a,b,c -
失效:
b、b,c、a,c(跳过 b) -
范围查询后失效:
a=1 and b>2 and c=3→ c 失效
4. 索引的设计原则
索引设计核心是按需创建、避免冗余:
- 优先使用联合索引 ,遵循最左匹配,高区分度字段放前面;
- 不为低基数列建索引,避免无序主键导致页分裂;
- 利用覆盖索引避免回表,禁止索引列运算、函数、隐式转换;
- 控制单表索引数量,读多写少多建,写多读少少建;
- 定期清理无用索引,平衡查询性能与写入开销。
最好的索引:最少数量、最大复用、覆盖查询、不拖慢写入。
5. 索引失效场景
-
where条件对索引列运算 / 函数 / 隐式转换 -
模糊查询
%前缀 -
or连接非索引列 -
联合索引不满足最左匹配
-
MySQL 优化器认为全表扫描更快
三、事务
1、事务四大特性
- 原子性(Atomicity) 全部成功 or 全部失败,用 undo log 保证。
- **一致性(Consistency)**执行前后数据合法,是最终目的。
- 隔离性(Isolation) 多个事务互不干扰,由 锁 + MVCC 保证。
- 持久性(Durability) 提交后永久保存,由 redo log 保证。
2、事务并发带来的3个问题
- 脏读读到其他事务未提交的数据
- 不可重复读一个事务内,两次查询结果不一样(针对 update)
- 幻读一个事务内,两次查询条数不一样(针对 insert/delete)
3、四大隔离级别
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 说明 |
|---|---|---|---|---|
| 读未提交 | ✅ | ✅ | ✅ | 不用 |
| 读已提交(RC) | ❌ | ✅ | ✅ | Oracle 默认 |
| 可重复读(RR) | ❌ | ❌ | ❌ | MySQL 默认 |
| 串行化 | ❌ | ❌ | ❌ | 性能极差 |
P:MySQL怎么解决幻读问题?
MVCC(普通查询)+ 间隙锁 + 临键锁(当前读)
4、大事务问题
大事务是运行时间长、操作数据多的事务。
大事务的典型场景:
- 一次插入 / 更新上万条数据
- 事务里夹杂外部接口调用(HTTP、RPC)
- 事务里做批量处理、循环、报表计算
- 事务开启后长时间不提交
(1) 大事务引发的问题
- 导致大量锁等待,并发性能暴跌
- 容易造成死锁
- 主从延迟严重
- undo log 膨胀,回滚极慢
- 占用连接不释放,导致连接池耗尽
大事务 = 锁长时间不释放 = 阻塞、死锁、延迟、雪崩
(2) 大事务产生的的常见原因
- 事务里调用远程接口(HTTP、Redis、MQ、RPC)
- 事务里批量处理大量数据(insert 1 万条、update 1 万条)
- 事务里做查询、计算、循环逻辑
- 手动开启事务忘记提交 / 回滚
- 长连接 + 长事务
(3) 如何解决/避免大事务
- 事务中禁止调用外部接口
- 批量数据拆分成小批量,小事务,快提交
- 查询逻辑放到事务外面
- 关闭自动提交,手动控制事务范围
- 避免长连接、长事务
- 使用异步、分步处理
(4) 生产中怎么发现大事务?
- 查看
information_schema.innodb_trx - 开启慢查询日志
- 监控事务执行时间
四、锁机制
1. InnoDB 锁分类
(1) 按锁粒度区分
-
行锁(Row Lock):InnoDB核心锁,锁一行,并发高
-
表锁(Table Lock):锁全表,并发低
(2) 按算法区分(解决幻读核心)
- 记录锁(Record Lock):锁具体某一行
- 间隙锁(Gap Lock):锁定一个范围,防止插入 → 解决幻读
- 临键锁(Next-Key Lock) :记录锁 + 间隙锁 ,在 RR(可重复读) 下生效,默认行锁算法,彻底解决幻读问题
(3) 按功能 / 兼容性区分
- 共享锁:允许多个事务同时读, 读与读不冲突,读与写互斥
- 排他锁:独占锁,读写、写写都互斥,
update / delete / insert自动加排他锁 - 意向锁(Intention Lock):表级锁,协调行锁和表锁,避免冲突
注:锁是加在索引上的,无索引会退化为表锁;
RC级别只有行锁;
RR 级别使用 行锁 + 间隙锁 + 临键锁 来解决幻读
2. 死锁
-
产生条件:互斥、请求与保持、不可剥夺、循环等待
-
排查 :
show engine innodb status -
避免:统一加锁顺序、小事务、设置超时时间
五、MVCC(多版本并发控制)
1、核心作用
实现无锁读写,提升并发性能
2、核心组件
-
undo log:保存历史版本,用于事务回滚和 MVCC
-
隐藏字段:
trx_id是事务 ID,roll_pointer指向 undo log -
Read View:事务快照,判断可见性
3、工作原理
-
读已提交:每次查询都生成新 Read View
-
可重复读:事务开始时生成一次 Read View(全程一致)
4、MySQL 锁、MVCC、事务隔离级别的关系
(1) 事务隔离级别是++标准规则++ ,规定了多事务之间的隔离程度,MySQL 默认是 RR(可重复读)。
(2) MVCC 是无锁的快照读 ++实现方案++,通过 undo log 多版本 + Read View 可见性判断,解决了脏读、不可重复读 ,并在RR 级别实现了事务内一致的查询效果。
(3) 锁机制(临键锁 / 间隙锁) 是当前读的++保障++ ,在 RR 级别下配合 MVCC,彻底解决幻读问题。
三者配合:MVCC 实现无锁读,锁机制保证写安全,事务隔离级别定义最终效果,共同支撑 MySQL 高并发事务。
六、MySQL vs PostgreSQL
MySQL是轻量级 开源关系型数据库,PostgreSQL :企业级、功能重型 开源关系型数据库,二者是全球最主流的关系型数据库。
核心差异:MySQL 轻量易用、高性能 ;PostgreSQL 功能最全、最标准、最强大。
1、核心区别对比
| 维度 | MySQL | PostgreSQL |
|---|---|---|
| 易用性 | 极简单,上手快 | 稍复杂,学习成本高 |
| 性能 | 高并发读写极快 | 复杂查询更强,简单场景略慢 |
| 功能完整性 | 够用,但不是最全 | 业界最完整,几乎支持所有 SQL 标准 |
| 事务 / ACID | 支持(InnoDB) | 完全严格 ACID,更可靠 |
| 并发能力 | 高并发简单查询强 | 复杂查询、多表关联更强 |
| 数据类型 | 基础类型够用 | 支持 JSON、数组、地理信息、枚举等超全类型 |
| 开源协议 | 双重协议,有商用限制 | 完全开源免费,无任何商用风险 |
| 适用场景 | Web、电商、APP、高并发 | 金融、地理信息、数据分析、复杂系统 |
| 生态 | 全球最大,云厂商全支持 | 生态完善,但略小于 MySQL |
2、最关键的4个差异
① 功能强弱:PostgreSQL 完胜
PG 被称为 "开源界的 Oracle",支持:
- 复杂 SQL(递归查询、多表联合、视图、存储过程)
- 原生 JSON、数组、枚举、地理信息(GIS)
- 自定义函数、自定义数据类型
- 更强大的索引、全文搜索
MySQL 只提供常用功能,复杂场景会吃力。
② 性能场景不同
- MySQL 赢在:高并发、简单查询、大量读写
- PG 赢在:复杂查询、多表关联、大数据量统计、数据分析
③ 标准性与严谨性
- PG :完全遵循 SQL 标准,数据一致性最严格
- MySQL:为了性能,部分规则宽松(比如允许非法日期)
④ 开源许可(商用非常重要)
- PostgreSQL :完全自由,可任意修改、分发、商用,无任何坑
- MySQL:被 Oracle 收购,协议有潜在商业风险