乐观锁 Optimistic Locking
乐观锁的概念
乐观锁机制采取了更加宽松的加锁机制。乐观锁是相对悲观锁而言,也是为了避免数据库幻读、业务处理时间过长等原因引起数据处理错误的一种机制,但乐观锁不会刻意使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性
CAS 乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。
为什么要用乐观锁 ?
例如银行转账流程
- B 的账户余额为 ¥300
- A 向 B 转账 ¥700
- 在 A 向 B 转账的同时 C 要 取走 B 的 ¥200(此时 B 的余额还是 ¥300)
- 这样的流程走下来后 B 的余额会覆盖成 ¥100
设置乐观锁后
- C 的取款操作: 会判断数据表当前的数据与操作时的数据是否相同(数据库中B的余额 300 是否与操作时已经查出来 B 的余额是否一致)
- 如果数据相同则会更新数据,否则会认为 已经查出来 B 的数据为过期数据
使用乐观锁后却产生了新的问题,就是ABA问题
- ABA问题: A 将 B 更新成 ¥1000 后 D 又将 B 更新为 ¥300,此时的 C 还认为 B 没有被更新过,C 的操作还是会成功.但不代表这个过程就是没有问题的
为了解决ABA问题,在数据库表中增加version字段
- 其目的是达到顺序递增,也就是修改这条数据后version会产生变化,这样其他正在操作这条数据的线程都会执行失败,因为他们都变成了过期数据
- 例子:
update t_user set sex = 1,version = version + 1 where user_id = 1 and version = 0;
这句SQL语句执行第一次会执行成功,执行第二次就会失败,因为version已经发生改变
发展趋势
在当前高并发,高可用等并发量较大情况下使用乐观锁基本成为第一选择
乐观锁并未真正的加锁,效率高。一旦锁的力度掌握不好,更新失败的概率就会比较高,也很容易发生业务失败
本文就先说到这里,有问题欢迎留言讨论