前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >并发实战理解MySQL的锁(悲观锁+乐观锁)

并发实战理解MySQL的锁(悲观锁+乐观锁)

原创
作者头像
小明爱吃火锅
发布2023-09-30 17:20:56
4130
发布2023-09-30 17:20:56
举报
文章被收录于专栏:小明说Java

一、前言

首先简单介绍一下悲观锁和乐观锁: 悲观锁: 比较悲观,一旦加锁,自身增删查改,其他线程无法任何操作,不能与其他锁并存。加锁方式 for update 乐观锁: 比较乐观,认为其他线程不会修改数据,一旦加锁自身可以增删查改,其他线程只能读。加锁方式 lock in share mode 两种锁的的释放都在 commit或者rollback 之后,否则就会一直持有。

场景:并发查询签到时,导致一个用户可以签到多次

解决办法:for update 来解决并发重复查询,保证每次只有只能一个线程执行查询

二、MySQL测试 开启两个查询窗口,开启手动提交事务,先后执行一下加锁查询语句

代码语言:javascript
复制
set autocommit=0;
BEGIN;

SELECT
	id,
	uid,
	diamond
FROM
	reward 
WHERE
	uid = '2300220816449831' 
	AND type IN ('SIGNIN') 
	AND ctime >= '2022-10-17'
	AND ctime < '2022-10-19')
for update;
	
COMMIT;

其中一个窗口执行完成之后,只要不执行 commit 操作,另一个窗口就会一直阻塞着。这样就可以说明 for update 避免并发重复查询,每一次只允许一个线程查询。 这时候其实可以去修改或者查询跟查询条件无关的数据,发现是可以修改成功的,但是如果是同种类型的数据,就会被阻塞,说明for update 加的是行锁。

三、java代码测试

根据上面签到重复问题,可以在查询的时候,增加 for update,其实也就是步骤一中的sql语句,不过注意需要在方法上加事务注解 @Transactional(rollbackFor = Exception.class)

Jmeter 测试配置:100个线程同时访问

1.Jmeter 测试——查询无加for update

发现同个用户id,同个时间点会有多条数据

2.Jmeter 测试——查询加for update,无@Transactional

结果发现也会重复插入数据

3.Jmeter 测试——查询加for update,加@Transactional

同个用户id,同个时间点只有一条数据

四、加的什么锁

如果查询条件用了索引/主键,那么select ..... for update就会进行行锁。

如果是普通字段(没有索引/主键),那么select ..... for update就会进行锁表。

但是如果select没有数据为空情况,会怎样呢?

其实也会,变成锁表,这时候,如果有insert或者Update操作,就会出现死锁情况。所以for Update的查询结果,应该作为判空处理,而不是判断非空。

这种情况其实很好验证,只要包含where条件的查询数据清空了,然后用jmeter并发请求,就可以重现:Deadlock found when trying to get lock; try restarting transaction

五、总结

1. for update可以加锁解决并发问题,并且还能作为分布式锁的一种实现方式,但是如果没有在事务内释放掉锁,就会导致死锁。 2. for update使用必须在事务内,也就是必须加注解@Transactional

我正在参与 腾讯云开发者社区数据库专题有奖征文

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、MySQL测试 开启两个查询窗口,开启手动提交事务,先后执行一下加锁查询语句
  • 三、java代码测试
  • 四、加的什么锁
  • 五、总结
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档