数据库乐观锁与悲观锁
演示案例
为何需要乐观锁,与悲观锁这样的锁?
id | name | money |
---|---|---|
1 | god | 1000 |
假设god同志的账上有1000元,现在有两个线程同时往他的账户上转钱。
1.A线程准备向god账户上转200,读取到账户上有1000元,事务还未提交
2.B线程准备向god账户上转100,读取到账户上有1000元,事务也还未提交
3.A线程提交了事务,god账户上变成了1200元,但是B线程此时不知道god账户上变成了1200
4.B线程随即也提交了事务,god账户上变成了1200,少了100元
因此,加锁的目的在于保障一个线程修改数据时,这个数据没有被其他的线程修改过
悲观锁与乐观锁的区别
1.在事务的基础上,悲观锁更适合短事务(长事务导致其他事务一直被阻塞,影响了系统性能),适用于查少改多
2.在事务的基础上,乐观锁更适合长事务,他的本质并不是锁,而是通过代码实现的。适用于查多改少
悲观锁的使用案例
在查的时候,对数据进行锁定。
在数据库中:for update
在Django中:select_for_update()
原生的sql:
1 开启事务
2 查询的时候加锁 ---》 select * from user where id =1 for update
3 结束事务锁被释放
django中:
1 开启事务
2 在查询的时候 ---》 user.objects.select_for_update().flilter(id=1).first()
3 事务结束锁被释放
乐观锁的使用案例
乐观锁的本质不是锁。他是通过代码来实现锁的。
方法:先拿到age数据,在修改的时候再次判断age是否一样。
(代码实现)目的:将这个数据中的age在原来的基础上+1
1 开启事务
2 查询的时候不做任何操作。data = user.objects.flilter(id=1).first()
3 在修在数据的时候。user.objects.filter(id=1,age=data.age).updata(age=data.age+1)
从而在我查询到我修改的时候,没有人改动过
4 如果3中的影响行数为0,证明数据被人修改。循环再次执行。如果为1,证明数据没人动过,修改成功
''' 如果是可重复读,上面的乐观锁无效,必须改成read committed'''