mysql的行索是在引擎实现的。但并不是所有引擎都支持行锁。不支持行锁的引擎只能使用表锁。 不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度 从两阶段锁说起 事务 B 的 update 语句会被阻塞,直到事务 A 执行 commit 之后,事务 B 才能继续执行。事务 A 持有的两个记录的行锁,都是在 commit 的时候才释放的。在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。 如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。 死锁和死锁检测 定义 当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待 的状态,称为死锁 出现死锁的策略 1、直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout 来设置。 (InnoDB默认是50s,正常在线服务接受不了。设置太小容易误伤) 2、发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。 (默认值是on,开启的,当然对数据库有额外负担) 死锁检测的过程 每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待, 也就是死锁 死锁检测的消耗 死锁检测的耗费代价是 O(n2)级别的。假设有 1000 个并发线程要同时更新同一行,那么死锁检测操作就是 100 万这个量级的。 解决死锁的思路 确保业务不会出现死锁,可以临时关掉死锁检测控制并发度