mysql 多条 update 语句怎么保证同时成功同时失败呢?

360 天前
 nerkeler

mysql 多条 update 语句怎么保证同时成功同时失败呢?

java 分布式 springcloud项目 数据库是mysql,我现在有一张产品库存表, 里面有多个产品,每行记录了这个产品的详情( ID 代码 名称 类型 库存量) 产品库存表 同一个产品只会存在一条记录。 产品库存表 大致结构

create table 产品库存表 (
id ..
产品代码..
产品名称..
产品类型..
库存量..
是否有效
修改时间
 创建时间
)

现在前端页面有个操作,大致就是将这些产品 分到一个产品包里 这个产品包 就是一个选择了不同产品和其数据的产品集合 产品包分配表另建的一张表

create table 产品包分配统计表(
id 
产品包名称
产品包 ID
创建时间
是否有效
)

产品包明细表

create table 产品包分配统计表(
id 
产品名称,
产品 ID ,
产品分配数量。
产品包名称
产品包 ID
创建时间
是否有效
)

简而言之,就是从 创建一个产品包 包含多个产品, 自己指定分配的产品数量,

所以 我从 产品的主库存 扣除分配给产品包的产品库存的时候, 需要保证这些产品修改 同时成功和失败,这样我好控制并发。

update 产品表    set 产品库存 =   产品库存 - 分配数量 where 产品库存 > 分配数量

这是一条产品更新的 语句,我现在想让 这些选了的产品 更新操作 同时成功,或者同时不执行,

我尝试 将多个 update 放在一行执行

update 产品表  set 产品库存  = case 条件(产品类型) when  xxx  then  对应的数量  
when xxx then 对应的产品数量 
...
end
when  产品库存 > case 产品类型  when  xxx  then 对应的数量

update 语句 条件不成立的时候 只会 让影响的行数 是 0 ,从而让满足条件的执行了,没满足的没执行。

各位有什么好办法吗

3475 次点击
所在节点    MySQL
36 条回复
goodryb
360 天前
以我不多的数据库认知, 你标题的需求应该会用到 事务
NoobNoob030
360 天前
触发关键词 事务
ysnow888
360 天前
cyrivlclth
360 天前
关键词,事务,隔离级别。。。
nerkeler
360 天前
@cyrivlclth msyql 隔离级别 没有权限修改, update 不满足条件的语句不会产生异常,只是 受影响的行数是 0
jowan
360 天前
突击抽查 事务的四大特性 请作答
258
360 天前
事务 or 分布式事务?
nerkeler
360 天前
不满足的 条件的 udpate 语句 受影响的行数是 0 的情况下 你们的意思会触发 事务?
jowan
360 天前
并发不大不考虑性能的话 你直接按正常逻辑写
事务里面加行锁 就行了 不用这么复杂
javalaw2010
360 天前
要么,你一条一条来,当某个 update 的的影响行数是 0 时,你 rollback ,要么,你有一个预期有多少行会受影响,如果实际影响的行数与预期不符,你 rollback 。异常这种东西一般发生在你代码里,跟数据库有什么关系。
nerkeler
360 天前
@jowan 更新的是多个产品记录,并不是一条记录,你这个思路要加表锁,比如 产品 1 减库存成功了,产品 2 减库存也成功了, 但是产品 3 不满足更新的条件,这时候需要把前两个更新操作回撤
nerkeler
360 天前
@javalaw2010 明白你的意思了,通过受影响的行数 判断,手动抛异常
jowan
360 天前
@nerkeler 对呀 transaction 里面 如果业务逻辑不符合的话 你主动 rollback 就行了啊 不就是这样用的吗
Plutooo
360 天前
这不是一个代码里 @Transaction 就解决的事情吗,要么手动抛异常,要么手动回滚
nerkeler
360 天前
学艺不精,谢了各位
jowan
360 天前
@Plutooo 他这个就是为了保证库存一致性的 并发不大的情况
@Transaction 后 可以按正常逻辑顺序来写 SQL
比如先减产产品库存表 查出来后 for update 加锁 再去加产品包表的库存
不需要 case when
buxudashi
360 天前
事务开启;

结果=false;
do{
执行 1 成功往下走,不成功 break;
执行 2 成功往下走,不成功 break;
......
结果=true;
}while(false);//保证只执行 1 次。

如果 true commit;
如果 false callback;
8355
360 天前
还好是 java 开发 如果是 php 的估计要被喷死了😀
nerkeler
360 天前
@buxudashi 老哥你这个能简化吧
事务开启;

产品 list.foreach(xxx ->
执行 xxx 不成功 callback;
)


commit;
xiaoHuaJia
360 天前
如果请求量不高就事务 。是如果是高并发场景 redis 加 lua 脚本

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/998095

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX