1. 行级锁
行级锁是有引擎层实现,即各个引擎层自己实现.MyISAM不支持行级锁。
1.1 两阶段锁
在InnoDB事务中,行锁是在需要的时候加上,但并不是在不需要了就立刻释放,而是要等到事务结束时才释放。例如以下操作中:
事务B只有等到事务A提交之后才能执行。
基于这个原因,所以如果在事务中需要锁定多个行,要把最可能造成冲突的锁放到事务最后。
1.2 死锁和死锁检测
死锁解决思路:
- 一直等待到事务超时.超时时间通过参数
innodb_lock_wait_timeout
设置,默认时间50s - 发起死锁检测,发现死锁后,主动回滚死锁联链条中的某一个事务,让其他事务可以继续执行。将参数
innodb_deatlock_detect
设置为on表示开启。默认是开启。
死锁检测的负担:
每一个事务被锁住的时候,就要看看他所依赖的线程有没有被别的线程锁住,如此循环检测,最后判断是否出现了循环等待,即死锁。如果并发量很高的表,这个个检测期间会消耗大量的CPU资源,却执行不了几个事务。
如何解决热点行更新导致的性能问题:
- 如果确保这个业务一定不会出现死锁,可以临时关闭死锁检测
- 客户端并发控制
- 在数据库中间件中实现并发控制
- 将逻辑上的一行改成物理上的多行来减少锁冲突。假如有个账号记录表,记录账号总额,可以将该该总额拆成十条记录存储,总额为这十条记录的总和。这样在更新时可以减少1/10的锁冲突。但是业务逻辑也会相应的增加复杂度。