暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Mysql 悲观锁

Johnny屋 2023-02-01
252

本篇主要来看看mysql中的悲观锁的 概念  类别 介绍了 排他锁和共享锁 以及 使用悲观锁的时候需要注意 行锁表锁 以及死锁的情况

1.mysql的悲观锁 概念

悲观锁[Pessimistic Concurrency Control]指的是 在操作数据的时候悲观的认为数据会发生冲突
, 所以在每次操作的时候都直接把数据给锁住🔒,这样其他的线程就只能阻塞住 无法操作, 所以悲观锁比较耗费时间, 一般悲观锁都是借助 数据库锁机制
在java中 synchronized 就是悲观锁 同一时刻只有一个线程能拿到锁 执行


2.悲观锁的类别

基于数据操作的 类型
分类

悲观锁分为 排他锁 和 共享锁

  • 排他锁[exclusive locks]: 简称 写锁, 是指 一个事物中获取了排他锁后 其他事物就无法获取锁进行读取和修改操作了
    ,获取排他锁的事务可以对数据行读取和修改。

  • 共享锁[shared locks]: 简称 读锁, 是指 多个事物可以对同一数据共享一把锁 都能访问读取到数据
    , 但是无法修改


2.1 排他锁

mysql 中可以使用 select ... for update 来应用悲观锁

select * from product_lock where id = 1 for update;

如果发生并发,同一时间只有一个线程可以开启事务并获得 id=1 的锁,其它的事务必须等本次事务提交/回滚之后
才能执行。这样可以保证当前的数据不会被其它事务修改。



2.2 共享锁

mysql 中可以使用 lock in share mode  来给语句添加 共享锁

select * from product_lock where id = 1 lock in share mode;

如果发生并发,如果有一个事物开启了 某数据的共享锁, 其他事物可以获取到这个数据的锁 进行读取 但是无法更新这个数据



3. 悲观锁 表锁行锁 注意事项

在使用悲观锁的时候 需要注意 表锁和行锁 以及死锁的情况, 默认情况MySQL InnoDB 默认行级锁
但是 行级锁都是基于索引的
 如果使用不当会导致 行锁变成表锁 降低性能


行锁条件

  1. where 后面查询条件字段 必须是 主键索引/索引

  2. 条件必须是 =  in 这种精确的 不能是 like 和 != 这种


3.1 未添加索引的字段查询

可以看到 因为行锁是基于索引的 如果没有索引 则是 表锁


3.2 添加了索引的字段查询

下面把 product_code 给添加了 索引 可以发现就是行锁



3.3 条件不是 精确

非精确查询 因为不能走索引 所以也不是行锁

# 都是表锁select * from product_lock where product_code like '%01' for update;# 都是表锁select * from product_lock where product_code != '1001' for update; 


3.4 死锁

死锁是 两个事物中 都先持有一个数据的锁, 然后互相再访问对方数据的锁 导致死锁,

如下 终端1 先获取了 id =1 的锁 , 终端2 也先获取了id =2的锁 , 但是后续 终端1 想去获取id=2的锁 终端2 想去获取id = 1的数据 此时就产生了死锁现象



建议: 让不同的 session 加锁的要有次序


总结

本篇主要介绍了 mysql 中悲观锁的一些基本的概念,  并且对悲观锁的分类 分别进行了演示,  最后总结了使用悲观锁的注意实现 包括 表锁和行锁 以及死锁的情况 , 需要注意 mysql InnoDB 默认行级锁 , 行锁是基于索引的 需要注意条件是精确的并且使用上了索引 否则会变成表锁


文章转载自Johnny屋,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论