innodb减少行锁对性能的影响

  基于两阶段协议,数据库的加锁和解锁分为两个阶段,加锁和解锁都应该在不同的阶段。下图操作序列中,事务B在操作id=1的数据的时候会阻塞住,直到事务A提交事务(在提交事务的时候统一解锁)才能执行自己的更新语句。

innodb减少行锁对性能的影响_第1张图片

为了减少发生冲突后阻塞的时间,如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。如上面的例子如果业务允许的情况下可以两条更新语句的顺序互换,让可能发生行冲突的id=1的更新语句尽量靠后。

死锁和死锁检测

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

下面是一个很简单的死锁例子:事务A和事务B在互相等待对方的资源释放。

innodb减少行锁对性能的影响_第2张图片

在innodb中,发生死锁一般有两种解决方法:

  • 进入等待直到超时,可以通过设置innodb_lock_wait_timeout调整超时时间
  • 设置死锁检测,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行,将参数innodb_deadlock_detect设置为on,表示开启功能。

第一种方法超时时间不好设置,时间设置长了线上等待无法忍受,短了如果本身是正常的操作不是发生了死锁,又会有很多误判。

一般用第二种,每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。这个过程是有性能开销的,要判断两两事务之间是否出现死锁要O(n*2)的复杂度,在1000个并发线程的情况下死锁检测就达到百万量级。

一般两种方法解决:

确保业务不会出现死锁,把死锁检测关掉

控制并发度,例如使用中间件做一层缓冲

 参考:

 mysql45讲

你可能感兴趣的:(mysql,数据库)