1.悲观锁(Pessimistic Locking):数据库物理锁 select * from table_name for update
悲观锁包括行级锁和表级索:行级锁是只锁定数据库的一行或者多行,表级锁是锁定数据库整张表。
以Mysql为例 Myisam引擎只支持表级锁,InnerDB支持行级锁和表级锁。 添加了锁的数据不能被其它事务再锁定,也不被其它事务修改(修改、删除) 。是表级锁时,不管是否查询到记录,都会锁定表(这里是和行级锁做对比 行级锁如果查不出对应的信息即使主键明确,而且for update 也没有行可以上锁)。
由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行TablLock (将整个资料表单给锁住)。 举个例子: 假设有个表单products ,里面有id,name,type 3列,id是主键。
例1:明确主键,且数据库能查出数据 -->row lock
SELECT * FROM products WHERE id='3' FOR UPDATE;
SELECT * FROM products WHERE id='3' and type=1 FOR UPDATE;
例2: 明确指定主键,且数据库查不出数据,无lock
SELECT * FROM products WHERE id='-1' FOR UPDATE;
例2: 无主键,table lock
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
例3: 主键不明确,table lock
SELECT * FROM products WHERE id<>'3' FOR UPDATE;
例4: 主键不明确,table lock
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;
我们可以通过开启mysql两个窗口进行测试,注意Mysql事务默认自动提交,我们设置SET AUTOCOMMIT=0 禁止自动提交.锁定语句放在begin....commit(事务)快中
优缺点:悲观锁大多数情况下依 靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库 性能的大量开销,特别是对长事务而言.例如商城看买一件东西,可以有成千上万的人想买这件商品,如果用了悲观锁,而先准备买的那个人期间可能有别事情一直没有提交,那么其他人就没法提交购买。
2. 乐观锁
乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本 ( version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。同时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号等于数据库表当前版本号,则予以更新,否则认为是过期数据。
Mybatis-Plus乐观锁插件 https://mp.baomidou.com/guide/optimistic-locker-plugin.html#主要适用场景