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

174 天前
 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 ,从而让满足条件的执行了,没满足的没执行。

各位有什么好办法吗

3207 次点击
所在节点    MySQL
36 条回复
uleh
174 天前
看了标题我以为是海量数据分布式更新还要保障高并发
进来一看。。。
nerkeler
174 天前
@uleh 让你失望了
ZField
174 天前
库存问题啊,省事的方案就是提到 redis 上面来处理 ,缓存都处理完了再落库。
直接 MySQL 的话,单机就锁库存,然后开启事务,手动判断,手动回滚。
totoro52
174 天前
判断是不是更新条数 0 0 就直接抛异常不就好了 剩下的都不走了 然后交给分布式事务去处理即可。
jackaluo
174 天前
chatgpt 的回复:
在多个并发更新操作中,确保同时成功或同时失败可以使用事务来实现。在 MySQL 中,您可以使用事务来包装多个 UPDATE 语句,以便它们要么全部成功,要么全部失败。这样可以确保数据的一致性。

以下是一个示例 Java Spring 代码,用于在分布式 Spring Cloud 项目中使用事务来实现这种需求:

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ProductService {

private final ProductRepository productRepository;

public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}

@Transactional
public boolean updateProductStocks(List<ProductUpdateRequest> updateRequests) {
try {
for (ProductUpdateRequest updateRequest : updateRequests) {
// 执行产品库存更新操作
int rowsUpdated = productRepository.updateProductStock(updateRequest.getProductId(), updateRequest.getQuantity());
if (rowsUpdated != 1) {
throw new RuntimeException("Failed to update product stock");
}
}
return true; // 所有更新成功
} catch (Exception e) {
// 发生异常,回滚事务
return false; // 任何一个更新失败都会导致整个事务失败
}
}
}
4ark
174 天前
@jackaluo 在这里贴 ChatGPT 的回复会被永久 ban
jackaluo
174 天前
@4ark 还有这种说法。。。那我删帖吧
buxudashi
174 天前
@nerkeler 不能简化。你的 foreach 里会全部执行。比如执行 10 次,第 3 次失败。你第 4 次和后面的循环已经没意义。后面的 commit 更加没意义。

正常情况下要退出后后 fallback.或者集体 commit.
siweipancc
174 天前
坏了,事务都没学,你没上大学?
nerkeler
174 天前
@buxudashi 我是使用抛异常的方式触发会滚,java 里这么写应该没问题
nerkeler
174 天前
@siweipancc 你要和我探讨探讨机械原理?
luomao
174 天前
楼主快说你是开发 node 的
xwayway
174 天前
@siweipancc 所以不是说看不起非科班,而是非科班……。完了说这句话我要被喷死,但是我还是想说
shea
174 天前
try 再加事务,还好你是用的 java ,要是 php ,现在你这帖已经是热帖了。
cyrivlclth
173 天前
@xwayway 我非科班哈,这种基础知识只能说这行门槛太低了。
julyclyde
173 天前
按说不应该存在 affected 为 0 的情况吧?
是不是应该先 select for update 锁上然后再 update ?

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

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

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

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

© 2021 V2EX