乐观锁、悲观锁
锁有什么用?
在数据库执行数据操作时,为了保证数据的
一致性
,即:A用户更新数据时,B用户不能更新!
在没有锁的情况下:
如果A、B都去针对相同的数据做更新操作。
数据库中的数据为最后提交的数据。
锁是什么?
在数据库的设计上,分为两种:
悲观锁
、乐观锁
。
悲观锁
:基于数据库的操作实现。
在数据库数据操作时,如果A用户查询到指定的数据,并增加for update
属性后
select * from user where id = 1
for update
;
此时的数据库将该数据加锁
,B用户需要修改该数据,只能在A用户事务提交
、或连接断开
后,才能执行数据操作。
- 乐观锁:基于算法的实现。
比如:在数据库中增加一个锁的处理列。
当A和B请求来操作时,都会拿到锁的处理列
,假设此时的数据为1
。
当A进行数据处理操作,此时不仅修改具体的数据信息,还会修改锁处理列
中的数据信息,假设此时修改数据为2
。
此时B处理数据,发现锁的处理列
数据变更,与其最初拿到的数据不一致,导致B无法执行数据的更新操作。
乐观锁的优点
悲观锁在执行时,会将其他处理数据库的请求拦截,使其他请求等待。
乐观锁在执行时,不会将数据锁住,让其他数据库请求等待。
Redis中的锁
在Redis中,直接支持使用乐观锁
。
如何观察Redis使用乐观锁
做数据操作处理?
使用两个不同的
sqlsession
实现数据的操作。
可以采取克隆当前会话
的操作,创建不同的sqlsession
。
以下为测试步骤:
- 在窗口1(Session 1)中执行如下操作:
创建一条记录数;
开启监听;
开启事务。
- 窗口2(Session 2)中执行如下操作:
针对
age
属性变更其数据信息;
发现在2中,可以变更数据,但1中的数据只是开启了事务,并未做处理。
- 返回窗口1(Session 1)修改数据,并执行事务的提交
发现此时事务的提交返回(nil)
!
总结
由于session 2 已经更新了原始数据,那么表示原始数据上的一个标记更新,这样当Session 1 在进行更新时,就会返回(nil)
,意味着本次事务提交更新操作失败!