1 分类
(1) 乐观锁
通过版本号和时间戳检测和处理并发冲突
(2) 悲观锁
1) 表锁和行锁
1‘ 表锁
对表加锁,开销小,没有死锁问题,但并发弱
2’ 页锁
开销、粒度和并发介于表锁和行锁之间,会出现死锁问题
3‘ 行锁
对数据行加锁,并发强, 但开销大且有死锁问题
注意:
- 更新锁,为了解决行锁升级(共享锁升级为排他锁)的死锁问题。
- MyISAM只能使用表锁,Memory支持表锁,BerkeleyDB支持表锁和页面锁,而InnoDB可以使用表锁和行锁。行锁通过对索引上的索引项加锁完成,只能在通过索引条件查询的场景中使用,否则使用表锁。
- 为了提升InnoDB表锁和行锁的效率,产生了意向锁(意向共享锁和意向排他锁)。
4‘ 行锁矩阵
行锁具有以下几种精确模式,用于控制锁粒度,减少冲突
意向锁(Insert Intention Lock)
InnoDB即支持表锁,又支持行锁。为了处理两种锁间的冲突,需要检测并避免。
1 判断表是否被其他事务加锁
2 遍历判断是否目标行被加锁 - > 效率低
意向锁标记表中是否存在某一行被锁住,申请表锁或行锁前需要获取表的意向锁
间隙锁(Gap Lock)
只锁索引之间的间隙,只针对辅助索引,不包含唯一和主键。只阻塞插入
记录锁(Record Lock)
只锁记录
Next-Key锁(Ordinary Lock)
同时锁记录和间隙
四种模式的写入兼容性,+表示兼容。
列名代表已有的锁,行名表示尝试获取的锁
2) 共享锁和排他锁
表锁和行锁都分为共享锁和排他锁。
共享锁排斥其他写,排他锁排斥其他读写。
1‘ 共享锁
事务执行SELECT时尝试加锁。
逐行锁定,读取后立即释放。
允许其他共享锁和更新锁。
2’ 排他锁
事务执行INSERT、UPDATE或DELETE时尝试加锁
排斥其他锁。
3‘ 更新锁
事务执行UPDATE时尝试加锁,用于避免两个持有共享锁的事务同时更新数据导致的死锁。
与共享锁兼容,与其他共享锁或排他锁互斥。
2 数据库隔离级别
未提交读:不使用锁,可能出现脏读
提交读:使用排他锁,可能出现重复读取数据不一致
可重复度:使用共享锁和排他锁,可能出现幻读
串行化:使用事务,性能较差
3 避免死锁经验
- 事务间按照相同的顺序访问数据,避免交叉访问引起的锁等待或死锁
- 尽量细化事务,减少事务占用的资源
- 一次性锁定所需的所有资源,避免死锁
- 降低隔离级别,减少使用锁
- 添加索引,为了使用更细粒度的行锁