mysql(八): 全局锁、行锁、表锁和死锁

1.全局锁

全局锁就是对整个数据库实例加锁,MySQL 提供了 flush tables with read lock (FTWRL) 的方式去加全局锁。当你需要让整个库处于只读状态的时候,就可以使用这个命令了,之后所有线程的更改操作都会被阻塞。该锁的主要是用在MyISAM这一类引擎对mysql数据备份上的使用。

逻辑备份工具是 mysqldump。当 mysqldump 使用参数–single-transaction的时候,导数据之前就会启动一个事务,来确保拿到一致性快照视图。而由于 MVCC 的支持,这个过程中数据是可以正常更新的。更新就是开一个线程拿取快照,然后恢复出一个当前时间的数据库备份。

为什么还需要 FTWRL 呢?
一致性读是好,但前提是引擎要支持这个隔离级别。比如,对于 MyISAM 这种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那么就破坏了备份的一致性。这时,我们就需要使用FTWRL 命令了。

2.表锁

MySQL 表锁有两种:
1.表锁 : 表锁的语法是 lock tables … read/write。可以用 unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。但是不仅会限制其他线程的读写,也会限制本线程接下来的操作。

2.元数据锁(meta data lock MDL): 元数据锁不需要显式使用,在访问一个表的时候已经被自动加上了。在MySQL 5.5版本中引入了MDL,当对一个表做增删查改的时候,加MDL读锁,当要对表做结构变更的操作的时候,加MDL写锁。

作用:当做增删改查时,如果表结构发生变化(某个字段被删除了),那么数据产生错误。使用MDL的写锁可以解决该问题。

3.行锁 (是在引擎层由引擎实现的)

不支持行锁的引擎意味着并发控制只能使用表锁,同一张表任何时刻只能有一个更新在执行,这就会影响到业务并发度。

InnoDB存储引擎是支持行锁的,MyISAM引擎不支持行锁,这也是MyISAM被InnoDB替代的重要原因之一。

两阶段锁:
一个事务不管持有几个行锁,都是在commit的时候才释放。
在InnoDB事务中,行锁是在需要的时候才加上,比如一个事务有 A行 B行两个update语句,对B行加行锁是在执行到B行update语句才加上的,并不是在事务开启时候加上。而且也不是不需要了就立刻释放,而是等到事务结束时一起释放的,这个就是两阶段锁协议。
知道了需要的时候才会加行锁对我们使用事务的帮助就是,如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。也就是被更新的概率比较多的行。这样容易造成锁冲突的行在一个事务中就不会停留很长的时间。

该秒杀业务文章讲了如何优化mysql行锁: https://blog.csdn.net/qq_35688140/article/details/101059991

4.死锁

在这里插入图片描述
这时候,事务A在等待事务B释放id=2的行锁,而事务B在等待事务A释放id=1的行锁。 事务A和事务B在互相等待对方的资源释放,就是进入了死锁状态。当出现死锁以后,有两种策略:

  • 一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数innodb_lock_wait_timeout来设置。
  • 另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数innodb_deadlock_detect设置为on,表示开启这个逻辑。

使用地中策略那一设置超时的时间,所以设置太长导致业务时延太大,设置太短容易误杀该事务。正常情况下我们还是要采用第二种策略,即:主动死锁检测,而且innodb_deadlock_detect的默认值本身就是on。主动死锁检测在发生死锁的时候,是能够快速发现并进行处理的,但是它也是有额外负担的。

参考文献:
https://blog.csdn.net/fouy_yun/article/details/87889415
《mysql实战45讲》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值