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


    1)MyISAM 被 InnoDB 替代的重要原因之一是什么?

    • MyISAM 引擎就不支持行锁,只能使用表锁,同一张表上任何时刻只能有一个更新在执行,影响到业务并发度。

    • InnoDB 是支持行锁的。

    2)两阶段锁协议是什么?

    • 在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放

    3)知道了两阶段锁协议,对我们使用事务有什么帮助呢?

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

    4)根据两阶段协议来实战优化的案例?

    • 买电影票业务,我们应该把影院账户余额增加这个语句放在最后,因为可能有很多的用户在同时买票。不要因为事务占有锁而影响我们其他的人买票,降低系统的并发度。

    5)如果这个影院做活动,可以低价预售一年内所有的电影票,而且这个活动只做一天。于是在活动时间开始的时候,你的 MySQL 就挂了。你登上服务器一看,CPU 消耗接近 100%,但整个数据库每秒就执行不到 100 个事务。这是什么原因呢?

    • 发生死锁

    6)MYSQL中死锁的解决策略?

    • 一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout 来设置。

    • 另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on(默认值就是on),表示开启这个逻辑。

    7)死锁的默认超时时间是多少?

    • 50s

    8)既然这么大不好,那为什么我们不把等待超时时间设置为1s呢?

    • 如果真的出现死锁的话那还好说,万一只是简单的等待那就造成误伤了。

    9)实际上我们应该选择哪种死锁的解决方案呢?

    • 选择上面6)的第二种,主动死锁检测

    10)主动死锁检测有哪些缺点?

    • 主动检测的业务:每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。

    • 假设有 1000 个并发线程要同时更新同一行,那么死锁检测操作就是 100 万这个量级的。最终没有死锁的话消耗大量的CPU资源,表面上看上去cpu很忙,但是缺没干了几件正事。

    11)既然主动检测特别耗CPU,那怎么解决由这种热点行更新导致的性能问题呢?

    • 就是如果你能确保这个业务一定不会出现死锁,可以临时把死锁检测关掉。

    • 另一个思路是控制并发度,并且这个并发控制要做在数据库服务端。因为客户端有很多。

    • 如果你有中间件,可以考虑在中间件实现;如果你的团队有能修改 MySQL 源码的人,也可以做在 MySQL 里面。基本思路就是,对于相同行的更新,在进入引擎之前排队。这样在 InnoDB 内部就不会有大量的死锁检测工作了。

    12)如果团队里暂时没有数据库方面的专家,不能实现这样的方案,能不能从设计上优化这个问题呢?

    • 将一行改成逻辑上的多行来减少锁冲突。以影院账户为例,可以考虑放在多条记录上,比如 10 个记录,影院的账户总额等于这 10 个记录的值的总和,每次要增加金额随便选一条就行。

    • 这类方案需要根据业务逻辑做详细设计,退票的时候当一部分行记录变成 0 的时候,代码要有特殊处理。

  • 相关阅读:
    BZOJ 1064 NOI2008 假面舞会
    p1186反素数(模板题)
    p1140【飞船控制站】
    p1164【立方体求和】
    p1103【base64编码】
    长沙集训(day不知道)伪总结(怕不是是一篇心得??)
    长沙集训day12
    长沙集训day10
    长沙集训day9
    长沙集训day8
  • 原文地址:https://www.cnblogs.com/YXBLOGXYY/p/15943677.html
Copyright © 2020-2023  润新知