1. 要点
- 行锁由各个引擎自己实现.
- 如果引擎不支持,则只能使用表锁.
2. 两阶段锁
当事务A提交后,事务B才能执行.
- InnoDB中,行锁时需要时才加上
- 直到事务结束才释放.
2.1. 影响
如果事务这种需要锁多个行,要把最可能造成冲突的锁尽量往后放.
2.1.1. 例子
一个事务:
- 用户扣钱
- 商户加钱=====>这个时最有可能造成冲突的.
- 记录交易日志
优化:把2放到最后,(延迟加锁时机)
- 用户扣钱
- 记录交易日志
- 商户加钱=====>这个时最有可能造成冲突的.
3. 死锁
并发中不同线程出现循环的资源依赖,互相等待别的线程释放资源.
3.1. 死锁解决方案
- 进入等待,直到超时.
innodb_lock_wait_timeout=默认是50
- 如果时间过短,可能会出现加上锁,正在起作用时,超时去掉了.
- 死锁检测:发现死锁后,主动回滚其中一个事务,让其他事务执行
innodb_deadlock_detect=on
- 优先推荐使用死锁检测.
3.2. 热点数据更新
如果出现热点数据更新,每个线程都需要检测自己的加入是否造成死锁.导致效率低下
解决:
- 业务上保证不出现死锁.
- 控制并发量.
- 业务上处理:把一个热点数据拆分.比如,商户可以有10个账户.更新时随机选择一个.
4. 问题
如何正确的删除表里的前10000行数据?
- 直接执行
delete from t limit 10000;
- 一次锁住10000行,执行时间长,大事务可能造成主从延迟
- 在一个链接中循环20次
delete from t limit 500;
- 这个这种.
- 在20个链接中执行
delete from t limit 500;
- 这是20个并发.会造成第2到20的链接被阻塞.