请教关于动态sql在并发场景下的安全性

yixueweima 2019-03-19 07:11:18
比如update table1 set filed1 = field1 - 1 where field - 1 >= 0 and id = 1,请问大家这条语句高并发会有风险吗。
例如出现这种情况,filed1 = 1时,两条语句同时判断field1 =1,这时候都会做减法 1-1一次,0-1一次。
我觉得这条语句的成败就在于读的时候是不是排他锁行或者表,但是没有专业的思路
...全文
122 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
yixueweima 2019-03-20
  • 打赏
  • 举报
回复
最上边的语句有点问题,where field应该是field1, 还是从新写一个没有歧义的 update mytable set myfiled = myfield - 1 where myfield - 1 >= 0 and id = 1
yixueweima 2019-03-20
  • 打赏
  • 举报
回复
经过mybatis+spring注解事务写的代码,和用jmeter并发测试(原谅我没有建立专门的表测试,只用了sys_user表的为int类型的user_sex性别字段作为测试字段),结果显示,当user_sex减到0时,对应的insert的条数不多不少等于目标字段的条数,所以现象上说明这条语句是没有并发风险的,原理上请大神们深入的解释下吧。 我之所以提出这个问题,原因是前两天去面试一家知名电商企业,讨论到减库存的问题时,我说我用这种做法,他说这样在超高并发下会出现问题,他建议用乐观锁方式,将时间戳直接拼到where条件中,但是我认为乐观锁在高并发时会造成大量的where条件不成立。 @Transactional public int updateSexCount(User user) { //并发减库存 int a = userDao.updateSexCount(user); if (a >0) { //如果上条成功,这里就增加一条数据 shopService.insert(new Shop()); } return a; } <update id="updateSexCount" parameterType="xxxx"> update sys_user set user_sex=user_sex - 1 where id = #{id} and user_sex - 1 >=0 </update>
yixueweima 2019-03-20
  • 打赏
  • 举报
回复
引用 4 楼 AHUA1001 的回复:
您担心的问题,应该不会存在,建议修改一下语句,会让直行效率有所提高。 先用id和field增加索引,然后修改语句如下: update table1 set filed1 = field1 - 1 where field >= 1 and id = 1 ;
谢谢,我今天打算实践一下,看看现象,虽然不能搞定里边的原理,但是如果出现错误就证明不行。
AHUA1001 2019-03-20
  • 打赏
  • 举报
回复
您担心的问题,应该不会存在,建议修改一下语句,会让直行效率有所提高。
先用id和field增加索引,然后修改语句如下:
update table1 set filed1 = field1 - 1 where field >= 1 and id = 1 ;
yixueweima 2019-03-20
  • 打赏
  • 举报
回复
引用 1 楼 trainee 的回复:
不用担心, 会排队, 当两个相同KEY的update 语句, 是排它行锁 . 可以用两个客户端, 交叉执行以下进行测试: START TRANSACTION update table1 set filed1 = field1 - 1 where field - 1 >= 0 and id = 1 COMMIT
谢谢,虽然update会加锁,但是会不会有可能内部执行的是读值和赋值两个过程呢,就像这样的 START TRANSACTION 1、select myfield from mytable where id = 1 ; 得要myfield的值是比如是1,计算出结果myfiled - 1 = 0 2、update mytable set myfield = 0 where 0>=0 and id = 1; COMMIT 这时候如果同时并发读,读出来的A执行1,读到值为1,B读到值为1,A加排它锁执行2 update mytable set myfield = 0 where 0>=0 and id = 1 释放排它锁,B加锁执行2 update mytable set myfield = 0 where 0>=0 and id = 1 释放排它锁。 这样无形中对数据库执行了两遍 update mytable set myfield = 0 where 0>=0 and id = 1,虽然结果对于这一行是不影响的。 但是如果事务中还有3、insert into。。。。。。 ,这句根据2返回的成功行数去操作,两个都发生了1行变动,那么就生成两条insert,其实就想要一条的。
trainee 2019-03-19
  • 打赏
  • 举报
回复
不用担心, 会排队,
当两个相同KEY的update 语句, 是排它行锁 .

可以用两个客户端, 交叉执行以下进行测试:
START TRANSACTION
update table1 set filed1 = field1 - 1 where field - 1 >= 0 and id = 1
COMMIT

56,678

社区成员

发帖
与我相关
我的任务
社区描述
MySQL相关内容讨论专区
社区管理员
  • MySQL
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧