锁机制与主从复制
MySQL 锁机制
锁用于控制并发访问,防止数据不一致。
锁粒度
| 锁类型 | 说明 | 并发度 | 开销 |
|---|---|---|---|
| 全局锁 | 锁定整个实例 | 最低 | 最小 |
| 表锁 | 锁定整张表 | 低 | 小 |
| 行锁 | 锁定具体行 | 高 | 大 |
| 间隙锁 | 锁定索引间隙 | 中 | 中 |
全局锁
sql
-- 全局读锁(整库只读)
FLUSH TABLES WITH READ LOCK;
-- 释放锁
UNLOCK TABLES;应用场景:全库备份(现在一般用 XtraBackup 替代)。
表锁
sql
-- 手动加表锁
LOCK TABLES users READ;
LOCK TABLES users WRITE;
-- 释放表锁
UNLOCK TABLES;MyISAM 只支持表锁,InnoDB 也支持表锁(意向锁 + DDL 锁)。
行锁(Record Lock)
InnoDB 行锁基于索引实现,如果查询没有走索引,会退化为表锁。
sql
-- 行锁(自动加锁)
BEGIN;
UPDATE users SET name = '张三' WHERE id = 1;
COMMIT;
-- 查看当前锁情况
SELECT * FROM performance_schema.data_locks;间隙锁(Gap Lock)
- 锁定索引记录之间的间隙,防止其他事务插入
- 在 REPEATABLE READ 级别下,为解决幻读问题引入
- 配合行锁形成 Next-Key Lock
索引:1, 3, 5, 7
间隙锁范围:(-∞, 1), (1, 3), (3, 5), (5, 7), (7, +∞)Next-Key Lock
行锁 + 间隙锁 = Next-Key Lock,锁定行及其前面的间隙。
sql
-- 锁定 id > 3 且 id <= 5 的范围(前开后闭)
SELECT * FROM users WHERE id > 3 FOR UPDATE;| 锁类型 | 范围 | 作用 |
|---|---|---|
| Record Lock | 锁定单行 | 防止行被修改/删除 |
| Gap Lock | 锁定间隙 | 防止间隙插入 |
| Next-Key Lock | 行 + 前间隙 | 防止幻读 |
死锁
死锁是指两个或多个事务互相等待对方释放锁。
死锁检测:
- InnoDB 自动检测死锁,回滚代价较小的事务
- 通过
SHOW ENGINE INNODB STATUS查看死锁信息
预防策略:
- 保持一致的加锁顺序
- 尽量使用 RC 隔离级别(减少间隙锁)
- 缩短事务执行时间
主从复制
复制原理
MySQL 主从复制基于 binlog(二进制日志):
主库(Master) 从库(Slave)
│ │
│ → Dump Thread │
│ ────────────── binlog ──→ │ I/O Thread → Relay Log
│ │ → SQL Thread → 重放
│ │流程:
- 主库:事务提交时写入 binlog
- I/O 线程:从库连接主库,拉取 binlog 写入 Relay Log
- SQL 线程:从库重放 Relay Log,同步数据
复制模式
| 模式 | 特点 | 优缺点 |
|---|---|---|
| 异步复制 | 主库不管从库是否收到 | 性能最好,可能丢数据 |
| 半同步复制 | 至少一个从库确认收到才提交 | 性能与数据安全平衡 |
| 组复制(Group Replication) | 多节点 Paxos 协议 | 强一致性,高可用 |
binlog 格式
| 格式 | 说明 | 特点 |
|---|---|---|
| STATEMENT | 记录 SQL 语句 | 体积小,但某些场景结果可能不一致 |
| ROW(默认) | 记录每行变更 | 体积大,但精确可靠 |
| MIXED | 混合模式 | MySQL 自动选择 |
InnoDB 建议使用
ROW格式,配合 GTID 使用效果最佳。
高可用方案
MHA(Master High Availability)
- 思路:主库宕机后,自动提升最新从库为新主库
- 缺点:需要手动搭建监控组件,已基本被弃用
Orchestrator
- 2016 年起流行的 MySQL 高可用管理工具
- 提供 Web UI 和 API,自动故障恢复
- 支持跨机房拓扑管理
- 当前社区主导
InnoDB Cluster
- MySQL 官方提供的高可用方案
- 基于 Group Replication + MySQL Router
- 支持自动故障转移
┌──────────────┐
│ MySQL Router │ ← 读写分离路由
└──────┬───────┘
┌─────────┼─────────┐
▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐
│ M1 │ │ M2 │ │ M3 │ ← Group Replication
└──────┘ └──────┘ └──────┘读写分离
- 主库处理写操作,从库处理读操作
- 通过 Proxy(ProxySQL、MySQL Router)或应用层实现
text
应用层 → ProxySQL → 主库(写)
→ 从库1(读)
→ 从库2(读)