Mysql锁-行锁

losetowin 发布于:2019-2-18 22:50 分类:技术  有 403 人浏览,获得评论 0 条 标签: mysql  

本文地址:http://www.dutycode.com/mysql_suo_hangsuo.html
除非注明,文章均为 www.dutycode.com 原创,欢迎转载!转载请注明本文地址,谢谢。

行锁

在引擎层由各个引擎自己实现

MyISAM不支持行锁,InnoDB支持行锁

  • 不支持行锁,意味着并发控制只能使用表锁,即同一时刻,同一张表只能有一个线程在更新,其余的操作需要等待。会严重影响到业务的并发度

概念: 针对数据表中的行记录的锁

两阶段锁协议

  • 在InnoDB事务中,行锁是在需要的时候才加上。 但并不是不需要的时候就释放,而是在事务提交结束之后才释放
  • 为了提高并发度,如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁往后放,减少行锁持有时间

死锁和死锁检测

  • 当并发系统中不同线程出现循环资源依赖,涉及到的线程都在等待其他线程释放资源时,就会导致这些线程进入到无限等待的状态,称为死锁
  • 如何解决数据库中行锁导致的死锁?

    • 策略1: 直接进入等待,直至超时。超时时间可以通过 innodb_lock_wait_timeout来设置

      • 默认值50s
      • 对线上实时服务来讲,超时时间过长意味着等待的获取锁的线程需要等待50s,无法接受。 但如果设置时间过短,又会导致误伤(比如,不是死锁,但被认为是死锁了)
    • 策略2:发起死锁检测,发现死锁之后,主动回滚死锁链条中某一事务,让其他事务得以继续执行。

      • 设置参数 innodb_deadlock_detect=on 表示开启死锁检测 (默认值是on)
      • 主动死锁检测,在发生死锁的时候是可以快速发现并处理的,但会有额外负担

        • 负担:当一个事务被锁的时候,需要检测他所依赖的线程有没有被锁住,如此循环,最后判断是否出现循环依赖(死锁)。 但如果所有的事务,都需要更新同一行的时候,就会导致每个新来的事务都需要检测是否由于自己的加入导致了死锁,时间复杂度O(n), 假如有N个线程加入,死锁检测操作就要在N*N这个级别上。 这个过程会消耗大量的CPU资源,最终导致CPU消耗很高,但却没处理几个事务
        • 如何解决由热点行更新导致的性能问题

          • 如果保证业务一定不会出现死锁,可以关闭死锁检测,存在风险。
          • 控制并发度,控制同一行的并发度

            • 服务端中间件层面上做控制
            • Mysql层面做修改,更新同一行,在进入引擎前先排队,这样InnoDB引擎就不会死锁检测
            • 不可在客户端做控制,因为客户端可能很多,无法做到最终的并发控制
          • 将数据拆分成多行的方式,减少并发下的锁冲突

            • eg:将一行拆分成10行,每次事务时,随机选一条更新,每次的冲突概率降为以前的1/10,可以减少锁等待个数,减少了死锁检测带来的CPU消耗
            • 需要业务上做业务聚合

版权所有:《攀爬蜗牛》 => 《Mysql锁-行锁
本文地址:https://www.dutycode.com/mysql_suo_hangsuo.html
除非注明,文章均为 《攀爬蜗牛》 原创,欢迎转载!转载请注明本文地址,谢谢。

上一篇:Mysql锁-表级别锁
下一篇:Mysql锁-全局锁