什么是悲观锁?

悲观锁是一种加锁的思想,也就是总是认为对数据的操作,是并发的,所有的数据都加锁。这里的锁与编程上的编程语言内的互斥锁(读和写都是串行处理的),起到的作用差不多,只不过这个锁,是数据库提供的。个人理解数据库事务中已经包含了写锁,悲观锁就就是在事务的基础上又加了读锁,成为真正的互斥锁。悲观锁相比mutex,效率并没有提升

悲观锁有什么用?相比mutex有什么优点?

多个进程/服务并发读写数据库,或者分布式部署微服务,假如使用mutex,进程间的锁不是同一把,一定会造成同步问题。使用悲观锁就可以解决这个问题,因为是数据库层面的锁,和进程服务并没有绑定关系。

如何使用悲观锁?

默认for update 是自动提交的(这里提交可以理解为解锁并且使语句生效),需要设置set autocommit=0,for update 是加在查询语句的后面

set autocommit=0;
select @@autocomit;
# for update 加锁
select * from house where id = 7 for update;
# commit 后提交数据并解锁
commit

悲观锁的注意事项?

fordate的两种情况:
where字段有索引:行锁
where字段无索引:表锁
结论:mysql 的加悲观锁的语句,中的where使用到的字段,必须有索引,否则会是表锁。

乐观锁

乐观锁假设一般情况下,并不会发生冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。
乐观锁的实现最常用的就是两种方式:

  • 使用时间戳,每次跟新数据,肯定要先查后改,我们把查出的updateAt时间戳当作update的查找条件,如果查不到,说明已经这段时间内又有一个进程修改了数据库,循环直到匹配到时间戳为止,然后更新update为time.unix()当前的时间戳
  • 设定版本,原理相同,每次更新时,版本加1
    乐观锁是在语言层面实现的,读者可以自己试试