一.mysql 悲观锁实现条件
①.查询和修改必须在一个事务中
/** * 更新Inter数据 */ @Override @Transactional public void updateInterData() { InterBean interBean = interMapper.queryInterData("interface1"); Long interUrl = interBean.getInterUrl(); interUrl+=1; interBean.setInterUrl(interUrl); interMapper.updateInterData(interBean); }
②. 查询语句末尾需要加for update
<select id="queryInterData" resultMap="baseResult"> select id,inter_number,inter_url from interface.lock_test_table where inter_number =#{interNumber} for update </select>
③.条件字段必须有索引(这个我不加索引也能实现,后面证明)
二.开始调用验证
@RequestMapping("/update") public String updateInterData(){ for (int i = 0; i < 5; i++) { threadPool.submit(()->{ lockService.updateInterData(); }); } return "OK"; }
使用线程池在controller 调用模拟高并发
测试场景1
①查询和修改在同一个事务下面
②for update
③查询条件字段加索引
测试结果:
调用前
调用后
可以看到在5个线程并发下修改数据由1每次加1现在是6了
测试场景2(将事务去掉其他条件保持不变)
测试结果:
调用前
调用后
锁没有生效,5个线程只加了1个值
场景3 (去掉for update,其他条件不变)
调用前:
调用后:
5个线程只加了1个值
场景3(去掉查询字段的索引,其他条件保持不变)
测试前:
测试后:
可以看到在5个线程并发下修改数据由1每次加1现在是6了(查询字段有无索引对锁没有影响,但是会让行锁变表锁,这个我后面写)
我的第一个博客,千里之行,始于足下.