mysql行锁怎么读,mysql锁---行锁

1、简述

MySQL 的行锁是在引擎层由各个引擎自己实现的。但并不是所有的引擎都支持行锁,比如MyISAM 引擎就不支持行锁。不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度。InnoDB 是支持行锁的。

行锁其实就是针对数据库数据行的锁定,同一时刻只能有一个事务去更新此行,如果有多个事务更新此行,要求顺序commit事务。

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

行锁的过程中是容易产生死锁的。

例如:

事务一:

update student set name = xiaoming where id =1

update student set name = yang where id = 2

事务二:

update student set name = zhang where id = 2

update student set name = huahua where id =1

在这两个事务中,事务一拿到了student 表ID= 1的行锁,并且更新了,与此同时,事务二拿到了student表ID = 2的行锁,这时事务一在等待事务二释放ID = 2 的行锁,事务二也在等待事务一拿到的ID = 1的行锁。这样相互的等待,并且执行不下去,就产生了死锁。

当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致

这几个线程都进入无限等待的状态,称为死锁。

我们需要怎么解决mysql中的死锁呢?

方法一:以通过mysql参数innodb_lock_wait_timeout 来设置。设置这个参数可以在事务线程等待多少秒后拿不到依赖线程,就认定产生了死锁。超时后主动释放。

方法二:发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on。

但是这两个方法都不完美,可以解决部分问题,但又会产生一些新的问题。方法一最暴力,直接设置超时时间,但是这超时时间是由人去设定的,设置短了会产生误杀(有的线程执行时间确实很长,但不是死锁的原因),设置长了不可能我们一个HTTP相应执行好几十秒。方法二确实能有效的检测死锁,但是他会把当前事务相关的线程都检查一遍(新加入得处于timewait线程都要检查),要是本来一个行的更新就频繁,并发大。那么需要检测线程就多了,时间花费暂且不谈,cpu的消耗是巨大的,有可能直接拉死系统。

那么有没有最好的解决方案呢?答案是没有最好,只有更好,需要设计更好的防治死锁,我们需要上面两个方法都开启,并且在设计数据库的访问时通过一些手段去避免方法二带来的CPU的巨大消耗。在些业务或者设计的时候就应该避免死锁,还有在实现业务的时候,避免某一条数据行的更新过于频繁和控制数据行更新的并发度(在服务端使用中间件技术)等等一些手段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值