mysql需要学会的知识_MySQL核心知识学习之路(4)

作为一个后端工程师,想必没有人没用过数据库,跟我一起复习一下MySQL吧,本文是我学习《MySQL实战45讲》的总结笔记的第四篇,总结了MySQL的锁相关知识。

1 全局锁

所谓全局锁,就是对整个数据库实例加锁,其命令为:

mysql>flush tables with read lock;

以下该命令会简称为FTWRL。

释放全局锁的命令为:

mysql>unlock tables;

需要注意的是:一旦加上全局锁,数据更新、数据定义和更新类事务都会被阻塞!

典型使用场景:全库的逻辑备份

对于全部库都是InnoDB引擎的库的话,建议使用 -single-transaction 参数,它对应用更友好。因为它基于MVCC(多版本并发控制)的支持,有自己的一致性视图,在整个过程中数据支持正常更新。

不建议使用 set global readonly = true 的方式实现全库只读,因为:

(1)修改global变量的影响面更大,某些系统可能会采用readonly作为业务参数使用。

(2)在异常处理机制上有所差异:

通过global方式之后如果客户端异常,数据库会一直保持readonly状态,会导致整个库长时间处于不可写状态,风险较高。

而FTWRL方式下,MySQL会自动释放这个全局锁,整个库回到可以正常更新的状态。

2 表级锁

MySQL中表级锁有两类:一是表锁,二是元数据锁。

表锁

表锁的语法为:lock tables ... read/write

它限制了别的线程,也限定了本线程接下来的操作对象。

表锁一般是在数据库引擎不支持行锁的时候才会被用到:

比如还在用MyISAM引擎,它不支持事务,需要安排升级引擎;

比如引擎支持事务了,但代码还没升级,将lock/unlock tables换为begin和commit;

元数据锁(metadata lock, MDL)

MySQL 5.5引入了MDL,不需要显示使用,在访问一个表的时候会自动被加上。

当对一个表做增删改查时,自动加MDL读锁(读锁之间不互斥);

当对一个表做表结构变更时,自动加MDL写锁(读写锁与写锁之间互斥);

MDL的作用:保证读写的正确性。

MDL带来的问题:修改表结构时申请MDL写锁,可能会导致锁表,后续业务操作均会阻塞。

解决办法:安全地给小表加字段。

解决长事务:找到一直占用MDL锁的长事务并kill掉;

设定等待时间:在alter table语句中设定等待时间,超时则释放,不阻塞后续业务语句的执行;

3 行锁

在MySQL中,行锁是引擎层由各个引擎自己实现的,但并不是所有引擎都支持行锁例如MyISAM就不支持。

事务A更新了一行,这时事务B也要更新同一行,那么事务B需要等待事务A的操作完成后才能进行

两阶段锁

两阶段锁协议:在InnoDB的事务中,行锁是在需要的时候才加上的,但并不是不需要了就立即释放,而是要等到整个事务结束时才释放。

给我们的启示:如果事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

案例:电影票在线交易业务

假设这个业务涉及三个操作:从顾客 A 账户余额中扣除电影票价;给影院 B 的账户余额增加这张电影票价;记录一条交易日志。

相比较下,影院B的账户更容易引发并发度冲突,所以应该把第二条语句放在事务内的最后一条,比如3-1-2的顺序,那么影院账户余额这一行的锁时间就最少。

4 死锁

所谓死锁,就是指当并发系统中不同线程出现循环资源依赖,各个线程都在等待其他线程释放资源时,就会导致各个线程进入无线等待的状态。

a19ef12f4077f8353e95a4342a0f8b95.png

图片来源:林晓斌《MySQL实战45讲》

应对策略

(1)直接进入等待,直到超时。通过参数 innodb_lock_wait_timeout 来设置,默认50s。

(2)发起死锁检测,即主动检测是否出现死锁,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。

开启死锁检测:innodb_deadlock_detect=on。

但是,主动检测死锁存在额外负担:当并发线程数量巨大时,需要消耗大量CPU资源去做检测,降低了事务执行效率。

那么,如何优化?一方面,可以临时关闭死锁检测(头痛医头的方法,不推荐);另一方面,控制并发度(可以做客户端并发控制,也可以做数据库服务端并发控制,但需要MySQL专家能够修改MySQL源码)。

5 小结

本文总结了MySQL的锁的相关知识,包括全局锁、表级锁(表锁和元数据锁)及行锁,最后了解了死锁的产生及应对策略。

参考资料

林晓斌(丁奇),《MySQL实战45讲》

👇扫码订阅《MySQL实战45讲》

1a34748f6fdb9a880fce194213c21876.png

67b3bf966b9dc406bee609baf52f53a8.png

作者:周旭龙

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值