暂无图片
分享
zj5220924
2019-05-22
oracle 类似更新库存问题,库存更新为负值

SQL1: update scott.test1 a set a.num=a.num-1 where a.id=1 and exists (select 1 from scott.test1 b where a.id=b.id and b.num>0);

SQL2: update scott.test1 a set a.num=a.num-1 where a.id=1 and a.num>0;

以上两个SQL按道理讲实现的效果应该一样,如果num为0了,后面的更新都会返回0条被更新,实际SQL1会出现被更新为负值的情况。详情如下

实验一:

初始==>a.id=1 a.num=1

image.png

session1==>update scott.test1 a set a.num=a.num-1 where a.id=1 and exists (select 1 from scott.test1 b where a.id=b.id and b.num>0);

session2==>update scott.test1 a set a.num=a.num-1 where a.id=1 and exists (select 1 from scott.test1 b where a.id=b.id and b.num>0);

session1==>commit;

session2==>commit;

结果==>a.num=-1

image.png


实验二:

初始==>a.id=1 a.num=1

image.png

session1==>update scott.test1 a set a.num=a.num-1 where a.id=1 and a.num>0;

session2==>update scott.test1 a set a.num=a.num-1 where a.id=1 and a.num>0;

session1==>commit;

session2==>commit;

结果==>a.num=0

image.png


收藏
分享
8条回答
默认
最新
谢金融

SQL2的结果好理解,至于SQL1为什么会是-1,这是因为select查询是一致性读返回的是查询开始时刻的数据,所以两次update同一行

暂无图片 评论
暂无图片 有用 0
zj5220924

SQL1为什么没有这个问题

暂无图片 评论
暂无图片 有用 0
zj5220924

说错了,SQL2为什么没有问题?

暂无图片 评论
暂无图片 有用 0
谢金融

SQL2是当前读不是一致性读,读的是当前块

暂无图片 评论
暂无图片 有用 0
zj5220924

那就说更新语句的所有子查询部分都是多版本读,主体部分为当前读对吧

暂无图片 评论
暂无图片 有用 0
谢金融

是的,你的测试已经足够说明了

暂无图片 评论
暂无图片 有用 0
谢金融

带有子查询的更新其实更新的数据就是子查询返回的行,是已经确认了的,直接根据rowid更新,我觉得就不存在所谓主体部分当前读了

暂无图片 评论
暂无图片 有用 0
zj5220924
问题已关闭: 问题已经得到解决
暂无图片 评论
暂无图片 有用 0
回答交流
提交
问题信息
请登录之后查看
邀请回答
暂无人订阅该标签,敬请期待~~
暂无图片墨值悬赏