数据库乐观锁与悲观锁

数据库乐观锁与悲观锁

演示案例

为何需要乐观锁,与悲观锁这样的锁?

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'''