7 怎么减少行锁对性能的影响?

7 怎么减少行锁对性能的影响?

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

这一章主要聊innodb的行锁,以及如何通过减少锁冲突来提升业务并发度。

从两阶段锁说起


Session a


Session b


begin;

update t set k=k+1 where id=1;

update t set k=k+1 where id=2;


begin;

update t set k=k+1 where id=1;


commit;

 

事务b的update语句在执行时候会是什么现象,假设id是t的pk

这个问题的结论取决于事务A在执行完两个update语句后,持有那些锁以及在什么时候释放,实际上事务b的update语句会阻塞,直到事务a的语句commit或者rollback,事务b才能够继续执行。

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

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

假设负责实现一个电影票在线交易业务,顾客A要在影院B购买电影票,简化一下,这个业务需要涉及到以下操作:

--1 从顾客A账户余额中扣除电影票价

--2 给影院B的账户余额增加这张电影票价

--3 记录一条交易日志。

也就说要完成这个交易,需要update两条记录并记录一个insert记录。当然,为了保证交易的原子性,我们需要把这三个操作放在一个事务中,那么,你会怎样安排这三个语句在事务中的顺序呢?

试想如果同时有另外一个顾客C要在影院B买票,那么这两个事务冲突的部分就是语句2了,因为它们要更新同一个影院账户的余额,需要修改同一行数据。

根据两阶段锁协议,不论你怎样安排语句顺序,所有的操作需要的行锁都是在事务提交的时候才释放,所以,如果把语句2放在最后,比如按照3,1,2这样的顺序,

那么影院账户余额这一行的锁时间就最少,这就最大程度地减少了事务之间的锁等待,提升了并发度。

现在由于正确的设计,影院余额这一行锁在一个事务中不会停留很长时间,但是这并没有完全解决。

如果在促销活动,大量的并发会导致mysql服务挂掉,这里说死锁和死锁检测

死锁和死锁检测

当并发系统中不同线程出现循环依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无线等待的状态,称为死锁


Session a


Session b


begin;

update t set k=k+1 where id=1;


begin;


update t set k=k+1 where id=2;


update t set k=k+1 where id=2;


update t set k=k+1 where id=1;

事务a在等待事务b释放id=2的行锁,而事务b在等待事务a释放id=1的行锁,互相等待就进入了死锁状态,出现了死锁状态,有两种策略:

--1 直接进入等待,直到超时,参数innodb_lock_wait_timeout

--2 发起死锁检测,主动回滚死锁链中的某一个事务,让其他事务继续执行,参数innodb_deadlock_detect=on,表示开启这个逻辑

在innodb中,innodb_lock_wait_timeout默认50s,如果采用这个策略,当出现死锁后,第一个被锁住的线程要50s才会出现超时,然后其他线程才可以继续执行,对于在线服务来说,这个等待时间是无法接受的。

但是这个innodb_lock_wait_timeout又不能设置很小的值,比如1s,出现了死锁是会很快解开,但是如果不是死锁呢,是锁等待呢,就会出现很多误伤。

所以正常情况采用策略2,主动监测死锁,参数innodb_deadlock_detect默认on。

但是如果并发度很高,所有事务都更新同一行,每个新来的被阻塞的线程都要判断会不会由于自己的加入导致了死锁,时间复杂度O(n)的操作,假设有1000个并发线程要同时更新同一行,

那么死锁检测操作就是100w这个量级的,虽然最终检测的结果是没有死锁,但是这会消耗大量的cpu资源。

另一个控制并发度,如果能够在客户端做并发控制,但是可能会由于客户端很多,也会有很高的并发,在数据库服务端做,如果有中间件,可以考虑在中间件实现,如果能修改mysql源码,

也可以在mysql里面做,基本思路就是相对于同行的更新,在进入引擎之前排队,这样在innodb内部就不会有大量的死锁检测工作了

但是,能不能从设计上来优化这个问题呢

可以考虑将一行改成逻辑上的多行来减少锁冲突,以影院账户为例,可以考虑放在多条记录上,比如10个记录,影院的账号总额等于这10个账户记录的值的总和,这样每次给影院账户修改金额的时候,

随机选其中一个记录来修改,这样每次冲突概率变为原来的1/10,可以减少锁等待个数,也就减少了死锁检测的cpu消耗。

这个方案需要根据业务逻辑做详细设计,如果有退款逻辑等。

思考题:

如果要删除一个表里的前10000行数据,以下三种方法:

--1 执行直接delete from t limit 10000;

--2 在一个连接中循环执行20次delete from t limit 500;

--3 在20个连接中同时执行delete from t limit 500;

原文地址:https://www.cnblogs.com/yhq1314/p/11103996.html

时间: 2024-11-07 12:38:38

7 怎么减少行锁对性能的影响?的相关文章

07 | 行锁功过:怎么减少行锁对性能的影响? 学习记录

<MySQL实战45讲>07 | 行锁功过:怎么减少行锁对性能的影响?  学习记录http://naotu.baidu.com/file/4cb2c22bd1b54678bf25d8af20bc70b8?token=f63a35dd193aa811 原文地址:https://www.cnblogs.com/jtfr/p/11260309.html

07 | 行锁功过:怎么减少行锁对性能的影响?

在上一篇文章中,我跟你介绍了MySQL的全局锁和表级锁,今天我们就来讲讲MySQL的行锁. MySQL的行锁是在引擎层由各个引擎自己实现的.但并不是所有的引擎都支持行锁,比如MyISAM引擎就不支持行锁.不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度.InnoDB是支持行锁的,这也是MyISAM被InnoDB替代的重要原因之一. 我们今天就主要来聊聊InnoDB的行锁,以及如何通过减少锁冲突来提升业务并发度. 顾名思义,行锁

Spring事务管理实现原理及MySQL InnoBD引擎行锁概述

Spring实现事务管理的机制 Spring事务管理是基于AOP编程思想实现,Spring框架被广泛使用的原因之一,就是提供了强大的事务管理机制. AOP是什么?我们常说的AOP并不是指一种开发技术,而是一种编程思想,AOP的核心概念就是面向切面编程,实现可插拔,降低程序之前的耦合性,提高重用性. Spring AOP 基于动态代理实现,一种是JDK动态代理,另一种是CGLIB动态代理. spring2.5之前声明式事务可以这样实现: ?<!-- 声明使用的spring事务管理器--> <

【转载】数据库大并发操作要考虑死锁和锁的性能问题

本文转载自:http://blog.csdn.net/yuanyuanispeak/article/details/52756167 1 前言 数据库大并发操作要考虑死锁和锁的性能问题.看到网上大多语焉不详(尤其更新锁),所以这里做个简明解释,为下面描述方便,这里用T1代表一个数据库执行请求,T2代表另一个请求,也可以理解为T1为一个线程,T2 为另一个线程.T3,T4以此类推.下面以SQL Server(2005)为例. 2 锁的种类 共享锁(Shared lock). 例1: -------

数据库行锁,表锁

锁主要用于多用户环境下保证数据库完整性和一致性. 我们知道,多个用户能够同时操纵同一个数据库中的数据,会发生数据不一致现象.即如果没有锁定且多个用户同时访问一个数据库,则当他们的事务同时使用相同的数据时可能会发生问题.这些问题包括:脏读.不可重复读和幻读 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据.因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正

MySQL中的锁(表锁、行锁)

锁是计算机协调多个进程或纯线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU.RAM.I/O)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所在有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素.从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂. 概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制. MySQL大致可归纳为以下3种锁: 表级锁:开销小,加锁快:不会出

MySQL中的锁(表锁、行锁,共享锁,排它锁,间隙锁)

本文参考: http://mysqlpub.com/thread-5383-1-1.html http://blog.csdn.net/c466254931/article/details/53463596 有很多是转载合并过来. 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的 计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数据库必须解决的一 个问题,锁冲突也是影响数据库并发访问性能的一个重

MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)

锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或县城并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一种供许多用户共享访问的资源.如何保证数据并发访问的一致性.有效性,是所有数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素.从这一角度来说,锁对于数据库而言就显得尤为重要. MySQL锁 相对于其他的数据库而言,MySQL的锁机制比较简单,最显著的特点就是不同的存储引擎支持不

MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)

原文地址:http://blog.csdn.net/mysteryhaohao/article/details/51669741 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或线程并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一种供许多用户共享访问的资源.如何保证数据并发访问的一致性.有效性,是所有数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素.从这一角度来说,锁对于