大家好,我是 Snow Hide,作为《MySQL 实战》这个专栏的学员之一,这是我打卡的第 5 天,也是我第 45 次进行这种操作。
今天我温习了该专栏里叫《全局锁和表锁 :给表加个字段怎么有这么多阻碍?》、《行锁功过:怎么减少行锁对性能的影响?》的文章。
关键词总结:锁分类、全局锁(加锁方法、应用场景、风险、建议使用 FTWRL 方式的两个原因)、表级锁(表级锁种类(表锁、元数据锁、MDL 读写锁))、支持行锁的引擎、两阶段锁(行锁的释放时间)、死锁和死锁检测(解决死锁的两种策略、解决热点行更新导致的性能问题)。
所学总结:
锁分类
全局锁、表级锁、行锁。
全局锁
加锁方法
FTWRL(Flush Tables With Read Lock),让整库处于只读状态,此时其他线程所运行的一些语句会被阻塞:数据更新(增删改)、数据定义(建表、修改表结构)、更新类事务提交。
应用场景
全库逻辑备份。
风险
- 主库加锁期间不能执行更新,业务暂停运作;
- 从库加锁期间不能执行主库同步过来的 binlog,导致主从延迟。
建议使用 FTWRL 方式的两个原因
- readonly 在一些系统中会被用作其他逻辑,例如判断是主库还是备库。因此修改 global 变量的影响比较大;
- 执行 FTWRL 后客户端如果发生异常断开,库全局锁会自动释放,并回到正常状态。如果设置为 readonly 期间客户端发生异常,库会一直保持 readonly 状态,不会回到正常状态。
表级锁
表级锁种类
表锁、元数据锁(MDL,Meta Data Lock)
表锁
lock tables … read/write。与 FTWRL 类似,可以借助 unlock tables 来释放锁或在客户端断开时自动释放锁。lock tables 除了限制其他线程的读写外,还会限制本线程接下来的操作对象。
元数据锁
无须显式声明,访问表时自动上锁,并保证读写正确性。
MDL 读写锁
- 读锁不互斥,可以多线程对表进行增删改查;
- 读写锁的写锁互斥,保证表结构变更的安全性。多线程按顺序操作表结构。
支持行锁的引擎
InnoDB 支持行锁。
两阶段锁
行锁的释放时间
等到事务结束时才释放。
死锁和死锁检测
解决死锁的两种策略
- 等待超时。设置超时参数:innodb_lock_wait_timeout;
- 发起死锁检测,回滚死锁链条的一个事务,让其他事务可以继续。设置参数 innodb_deadlock_detech 为 on。
解决热点行更新导致的性能问题
- 在确保业务不会出现死锁的情况下临时关掉死锁检测,关掉死锁检测可能会出现大量超时;
- 控制并发度。同行更新在进入引擎之前排队,以减少 InnoDB 内部的死锁检测工作;
- 通过将一行改成逻辑上的多行来减少冲突,以减少锁等待个数。
末了
重新总结了一下文中提到的内容:全局锁、表级锁、全局锁应用场景、表锁应用场景、MDL 元数据锁、行锁、两阶段锁协议、死锁以及死锁检测、控制访问相同资源的并发事务量。