两阶段锁:事务在用到记录时申请锁资源,当不需要之后不会立刻释放锁,而是需要等待事务结束之后释放锁资源。
- 两阶段锁的应用:电影院买票,交易时涉及三条更新操作。
- 用户账户余额减少
- 电影院账户余额增加
- 添加一条交易记录 由于电影院余额增加这个操作最容易出现锁资源争抢,所以需要将这个操作放在一个事务的最后面开始执行。减少一个事务占用锁的时长,提高并发度。
-
死锁和死锁检测
mysql处理死锁有两种方式:
- 死锁线程进行等待,直到超时,超时之后线程退出,释放锁资源,死锁现象解决。等待时间通过innodb_lock_wait_timeout参数进行设置,默认时50s,这个时间过长,在线上环境下无法等待这么长的时间,设置太小也不行,有可能只是进行锁等待,线程就直接退出,浪费资源。
- 主动死锁检测,通过innodb_deadlock_detect为on,当出现死锁时,会对某个事务进行回滚,释放所资源来解决死锁问题,但是在检测是否出现死锁会消耗cpu的资源。假设现在又1000个线程对同同一行进行更新,每个线程进行阻塞等待锁资源的时候都需要检测自己持有其他锁资源,并且因为自己的加入而出现死锁问题,这个时候时间复杂度就达到100万的级别。cpu的性能消耗高,实际执行的事务数量很少。
-
针对死锁检测带来的问题,可以从以下三个方面来解决:
- 关闭死锁检测,这就导致只能使用超时方案来解决,这对用户体验感影响极大。
- 控制业务的并发度,通过中间件,或者修改mysql源码来解决
- 通过业务上的设计来减少死锁现象的发生,比如将电影院账户余额记录分为多条记录,这样任意取一条进行更新操作,都可以实现业务逻辑上的完整,求影院账户时进行汇总相加即可。