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 默认行级锁 , 行锁是基于索引的 需要注意条件是精确的并且使用上了索引 否则会变成表锁
标签:product,行锁,索引,悲观,Mysql,表锁,id From: https://www.cnblogs.com/tianxc66/p/17567750.html