行锁功过:怎么减少行锁对性能的影响?

从两阶段锁说起

实际上事务B的update语句会被阻塞,直至事务A执行commit之后,事务B才能继续执行。

在InnoDB事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是等到事务结束才释放,这就是两阶段锁协议。

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

死锁和死锁检测

当并发系统出现资源循环依赖,就会导致这几个线程处于无限等待状态,称为死锁

两种解决死锁的策略:

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

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

使用show variables like 'innodb_deadlock_detect';可以查看系统参数。

问题

如果你要删除一个表里面的前 10000 行数据,有以下三种方法可以做到:

  • 第一种,直接执行 delete from T limit 10000;

  • 第二种,在一个连接中循环执行 20 次 delete from T limit 500;

  • 第三种,在 20 个连接中同时执行 delete from T limit 500。

一般会选择第二种。

第一种方式单个语句占用时间长,锁的时间也比较长;而且大事务还会导致主从延迟。

第三种方式会人为造成锁冲突。

Licensed under CC BY-NC-SA 4.0
陕ICP备16008414号
使用 Hugo 构建
主题 StackJimmy 设计