MYSQL45讲学习笔记

本文介绍了MySQL中InnoDB引擎的行锁机制,强调了索引对行锁的重要性,以及两阶段锁协议如何导致死锁。通过案例分析了死锁的产生,并提出了两种避免死锁的策略:设置锁等待超时或启用死锁检测。讨论了死锁检测带来的性能影响,并提出了降低事务并发度和调整SQL执行顺序作为解决方案。总结了避免死锁及其性能损失的关键点。
摘要由CSDN通过智能技术生成

7.行锁功过

MYSQL的行锁是引擎层的,由各个引擎来实现,InnoDB支持行锁,而MYSQL原生的存储引擎MyISAM不支持行锁,也不支持事务,这是它被InnoDB取代的一个重要原因。

首先行锁是添加在索引上,如果where关键字后面的列没有索引,那么会导致锁表。

两阶段锁

行锁在需要用到的时候会被获取,但是并不会立刻释放,而是在事务提交的时候释放,这就是两阶段锁。

 如图所示,假设id为表T主键,那么上图的事务会有什么结果?

事务B的操作会被阻塞,等待事务A commit之后才会执行。

知道了两阶段锁的特性之后,我们可以把最容易造成锁冲突,或者容易锁住多行的SQL语句放在合适的执行顺序上。

死锁和死锁检测

 上图中的事务A等待事务B释放id=2的行锁,事务B等待事务A释放id=1的行锁,两个事务产生锁资源循环依赖,造成死锁(无期限等待)。

如何避免死锁

一般有两种策略:

1.直接进入等待,直到超时,可以设置参数innodb_lock_wait_timeout,默认值为50S

2.死锁检测,发现死锁后,主动回滚死锁链中的某一个事物,使其他事物可以继续执行,可以设置参数innodb_daedlock_detect,默认开启

 第一种策略,默认时间为50S,对于线上业务来讲,显然是不可接受的,但是我们也不能把时间设置的太短,如1S,可能有一些事物只是在正常的锁等待,容易造成误伤。

所以我们一般情况下还是使用第二种策略,即:死锁检测,而且死锁检测默认开启,但是死锁检测也是有额外负担的。

 每当有事务被锁住的时候,都会去检测它锁依赖的线程有没有被别人锁住,如此循环,看有没有出现循环等待时间,即死锁。

如果有一个线程锁住了某一行纪录,之后有1000个线程要获取这一行记录,那么这个时候,死锁检测的操作就是一百万量级的,这时候就会看到cpu的使用率非常高,但是可能系统的QPS很低,也就是处理事物的量很低。

如何避免因死锁造成的性能损失

关闭死锁:

如果确定系统不会产生死锁,那么可以主动关闭死锁检测。但是这种方案有风险。

控制事务并发度:

我们可以降低事务的并发度,可以在服务端控制。

在设计上降低并发度,比如给某一个热点字段分成10个字段,每次随机写某一个字段,这样并发就减少为原来的十分之一,不过这样代码也需要考虑更多,需要做一些特殊处理。

小结:

本节学习了行锁的两阶段锁协议,死锁和死锁检测,以及如何避免因死锁检测造成的性能损失。

我们了解了两阶段锁协议以后,我们可以把会所住多行的SQL操作放到事务的最后执行,以减少死锁的概率。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值