悲观锁
共享锁
、排他锁
共享锁,也就是其他事务可以并发读(其他事务也需要加共享锁),但是不能写。
排它锁,其他事务不能并发写也不能并发读。
乐观锁
乐观锁其实也不是实际的锁,甚至没有用到锁来实现并发控制,而是采取其他方式来判断能否修改数据。乐观锁一般是用户自己实现的一种锁机制,虽然没有用到实际的锁,但是能产生加锁的效果。
乐观锁基本都是基于 CAS(Compare and swap)算法来实现的。
主要有以下几种方式:
版本号标记
:在表中新增一个字段:version,用于保存版本号。获取数据的时候同时获取版本号,然后更新数据的时候用以下命令:update xxx set version=version+1,… where … version="old version" and ....
。这时候通过判断返回结果的影响行数是否为0来判断是否更新成功,更新失败则说明有其他请求已经更新了数据了。时间戳标记
:和版本号一样,只是通过时间戳来判断。一般来说很多数据表都会有更新时间这一个字段,通过这个字段来判断就不用再新增一个字段了。待更新字段
:如果没有时间戳字段,而且不想新增字段,那可以考虑用待更新字段来判断,因为更新数据一般都会发生变化,那更新前可以拿要更新的字段的旧值和数据库的现值进行比对,没有变化则更新。所有字段标记
:数据表所有字段都用来判断。这种相当于就、不仅仅对某几个字段做加锁了,而是对整个数据行加锁,只要本行数据发生变化,就不进行更新。
总结
悲观锁和乐观锁大部分场景下差异不大,一些独特场景下有一些差别,一般我们可以从如下几个方面来判断:
1.响应速度
:如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁
2.冲突频率
:如果冲突频率非常高,建议采用悲观锁,保证成功率,如果冲突频率大,乐观锁会需要多次重试才能成功,代价比较大
3.重试代价
:如果重试代价大,建议采用悲观锁
评论