从两阶段锁说起
实际上事务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。
一般会选择第二种。
第一种方式单个语句占用时间长,锁的时间也比较长;而且大事务还会导致主从延迟。
第三种方式会人为造成锁冲突。