怎么减少行锁对性能的影响()

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 的时候,代码要有特殊处理。

    推荐阅读