三.锁机制深度解析
锁类型:共享锁(S)、排他锁(X)、意向锁(IS/IX)、间隙锁(Gap Lock)、临键锁(Next-Key Lock)
死锁产生条件:互斥、持有等待、不可剥夺、循环等待
接下来我们看看InnoDB锁的层次结构
锁的粒度层次
1. 表级锁(Table Lock)
- 意向共享锁 IS
- 意向排他锁 IX
- 自增锁 AUTO-INC
2. 行级锁(Record Lock)
- 共享锁 S(SELECT ... LOCK IN SHARE MODE)
- 排他锁 X(UPDATE/DELETE/INSERT)
3. 间隙锁(Gap Lock)
- 锁定索引记录之间的"间隙"
- 防止幻读(Phantom Read)
4. 临键锁(Next-Key Lock)
- Record Lock + Gap Lock 的组合
- 默认在 RR 隔离级别使用
意向锁------用于解决表锁和行锁当然冲突
问题场景:
事务 A 想对某行加 X 锁
事务 B 想对整个表加 X 锁(如 DROP TABLE)
如何快速判断是否有冲突?
↓
解决方案:意向锁(Intention Lock)
事务 A 加行锁前,先对表加 IX 锁
事务 B 检查表级锁时,看到 IX 就知道了
"表中有行被锁定了",没有必要遍历所有行
锁兼容性矩阵

Gap Lock 与Next-Key Lock 的精确理解

这样我们就保证了数据的完整性,不让随意修改
接下来我们来分析分析一下Gap Lock的作用,我们通过对比有无Gap Lock来理解

这个就和我们提高隔离级别一样的,加上Gap Lock之后,我们就可以锁住这个数据之间的空隙,不让其他用户的修改我们的表,让我们在二次查询时候以为数据库有报错问题,也就是所谓的幻读
死锁的四个必要条件与检测

在InnoDB里面死锁检测机制:
1.它会使用wait-for graph(等待图)去检测循环
2.检测到死锁之后,会选择Undo量最小的事务作为牺牲品回滚(撤回之前操作)
3.innodb_deadlock_detect:是否开启死锁检测(高并发时关闭可能更好)
4.innodb_lock_wait_timeout:锁等待超时时间

现在我们开始实战一下死锁
建表

事务A,等待事务B

好的,我们发现了一个报错

没错,这就是说遇到了死锁
嗯,不错,全部对上了

四.连接池优化
什么,有没有听说过数据库连接是昂贵资源,其实我之前也不知道,在对比之下会有这么的资源消耗
创建一次数据库连接的代价
-
TCP 三次握手
-
MySQL 认证(密码校验、权限验证)
-
分配线程/内存资源
-
初始化会话状态(变量、字符集等)
总耗时:~ 几十到几百毫秒
对比:SQL 执行可能只需 1ms
MySQL的线程模型
MySQL 经典线程模型(One-Thread-Per-Connection)
sql
连接 1 ──→ 线程 1 ──→ 执行 SQL
连接 2 ──→ 线程 2 ──→ 执行 SQL
连接 3 ──→ 线程 3 ──→ 执行 SQL
...
问题:1000 连接 → 1000 线程 → 大量上下文切换
C10K 问题
MySQL 企业版/Percona/MariaDB 的线程池:
sql
连接 1 ──┐
连接 2 ──┼──→ 线程池 ──→ 工作线程
连接 3 ──┘ (少量线程)
...
线程池将 SQL 任务分发给有限的工作线程
减少线程切换开销,提高并发能力
我们从就可以发现经典模型它的漏洞是很多的,它是一个一个的连接执行(单一)
而线程池则是将它所有的连接集合在一个线程池里面,直接形成一个工作链(线程),既高效又成本低
连接池的核心设计原理

连接池大小的黄金法则
连接数计算公式(来自 PostgreSQL 作者)
sql
连接数 = (核心数 × 2) + 有效磁盘数
例如:8 核 CPU + 1 块 SSD
连接数 = 8 × 2 + 1 = 17
注意:这是数据库端的总连接数上限
如果多个应用服务端连接同一数据库,那么这就需要分摊
这样一看,难道我们的连接数是越大越好么,我们看看下面的案例
sql
连接数 = 200 的情况:
CPU 时间片轮转:
每个线程运行 5ms → 切换 → 下一个线程
200 个线程,一轮切换耗时 ~ 10ms
实际 SQL 执行 1ms,但等待 CPU 时间 9ms
CPU 大量时间花在上下文切换上
结果:吞吐量下降,延迟上升,CPU 飙高
这也没有越好,反倒比起前面的还逊色了,所以我们还是需要适当的值即可
连接池参数调优原理

这只是连接池的理论知识,后面我搭建实操项目,实操演练再说
查看连接状态

查看状态及详情

看看有没有连接错误过

非常好,0失误
sql
-- 查看当前连接状态
SHOW STATUS LIKE 'Threads_%';
SHOW STATUS LIKE 'Connections';
SHOW STATUS LIKE 'Max_used_connections';
-- 查看当前连接详情
SHOW PROCESSLIST;
SELECT * FROM performance_schema.threads;
-- 计算连接池建议大小(参考公式)
-- 连接数 ≈ (核心数 * 2) + 有效磁盘数
-- 例如 8 核 SSD:8*2+1 = 17 左右
-- 查看连接错误
SHOW STATUS LIKE 'Aborted_%';
哎,学好累,还有好多要学......
目录
[Gap Lock 与Next-Key Lock 的精确理解](#Gap Lock 与Next-Key Lock 的精确理解)
[接下来我们来分析分析一下Gap Lock的作用,我们通过对比有无Gap Lock来理解](#接下来我们来分析分析一下Gap Lock的作用,我们通过对比有无Gap Lock来理解)
什么,有没有听说过数据库连接是昂贵资源,其实我之前也不知道,在对比之下会有这么的资源消耗