本篇主要来看看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 默认行级锁
但是 行级锁都是基于索引的
如果使用不当会导致 行锁变成表锁 降低性能
行锁条件
-
where 后面查询条件字段 必须是 主键索引/索引
-
条件必须是 = 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屋):Mysql 悲观锁
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/105521.html