程序员技术干货

MySQL/InnoDB 的事务隔离级别和锁

2017-07-16  本文已影响254人  riveraiyanzi

事务的隔离级别

读分为快照读和当前读。用 MVCC 可解决快照读的脏读、幻读问题,不需要上锁。

具体可看

避免死锁

既然上锁,一不注意就可能出现死锁。为了避免死锁,一般有三种手段

  1. 按相同的顺序加锁,一次锁定需要的资源
  2. 加锁时限
  3. 死锁检测

具体到应用层面我们可以:

  1. 以固定的顺序访问表和行。将两个事务的 sql 顺序调整为一致
  2. 大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小
  3. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率
  4. 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为 gap 锁造成的死锁
  5. 为表添加合理的索引。如果不走索引将会为表的每一行记录上锁,死锁的概率大大增大

这主要体现的是手段 1 的思想。在 InnoDB 中有死锁检测机制。InnoDB 可以主动探知到死锁,并回滚了某一苦苦等待的事务。那么它是怎么探知到死锁的呢?

  1. 直观方法是在两个事务相互等待时,当一个等待时间超过设置的某一阀值时,对其中一个事务进行回滚,另一个事务就能继续执行。这种方法简单有效,在 InnoDB 中,参数 innodb_lock_wait_timeout 用来设置超时时间
  2. wait-for graph 原理

具体可看

InnoDB 的死锁检测机制相当于最后一道防线。也正因为 InnoDB 需要做死锁检测, 而且死锁检测算法的时间复杂度和并发事务是指数的关系(没有求证过,在一个演讲中看到这个说法),所以并发很高的时候,这个机制会占用很高的 CPU。

上一篇下一篇

猜你喜欢

热点阅读