引言
悲观锁和乐观锁指的并不是一种锁,而是一种思想,一种并发控制的方法。
在事务并发执行的情景中,可能存在多个用户同时更新同一条数据的情况,这可能会产生冲突导致丢失更新或者脏读。
- 丢失更新是指一个事务的更新覆盖了其他事务的更新结果
- 脏读是指当一个事务读取了其他事务没有完全执行的保存在数据库日志中的结果,也就是其他事务未提交的结果。
一、悲观锁
在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作读某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。
悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;另外,在只读型事务处理中由于不会产生冲突,也没必要使用锁,这样做只能增加系统负载;还有会降低了并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数据。(摘抄自*)
二、乐观锁
在关系数据库管理系统里,乐观并发控制(又名“乐观锁”,Optimistic Concurrency Control,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。
乐观并发控制多数用于数据争用不大、冲突较少的环境中,这种环境中,偶尔回滚事务的成本会低于读取数据时锁定数据的成本,因此可以获得比其他并发控制方法更高的吞吐量。(摘抄自*)
三、两种锁的使用场景
乐观锁适用于读情况比较多的场景,写情况不多的情况下,不容易产生冲突,不加锁会增大数据库系统的吞吐量。
悲观锁适用于写情况比较多的场景,写情况多冲突也容易发生,保守一些比较好,尽管会减小吞吐量,但总比引起冲突。
四、乐观锁的两种实现
(1)校验版本号
在事务执行前读取当前数据的版本号(Version)到缓存,当前事务提交前将缓存中的版本号和当前的版本号进行对比,若两个版本号相等则代表当前事务执行期间没有其他事务对数据进行修改,可提交。反之,好吧,我也没搞清楚会怎么样(待更新)
(2)时间戳