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 ,从而让满足条件的执行了,没满足的没执行。
各位有什么好办法吗
我统一回复下吧,
sql
异常的情况下被动回滚数据,因为update操作 在这里 我认为的不成功是 没有更新成功,也就是受影响的行数是 0 ,并没有产生SQL
异常。让我一时没有想到去主动控制。 1
goodryb 347 天前 1
以我不多的数据库认知, 你标题的需求应该会用到 事务
|
2
NoobNoob030 347 天前
触发关键词 事务
|
3
ysnow888 347 天前
|
4
cyrivlclth 347 天前
关键词,事务,隔离级别。。。
|
5
nerkeler OP @cyrivlclth msyql 隔离级别 没有权限修改, update 不满足条件的语句不会产生异常,只是 受影响的行数是 0
|
6
jowan 347 天前
突击抽查 事务的四大特性 请作答
|
7
258 347 天前
事务 or 分布式事务?
|
8
nerkeler OP 不满足的 条件的 udpate 语句 受影响的行数是 0 的情况下 你们的意思会触发 事务?
|
9
jowan 347 天前
并发不大不考虑性能的话 你直接按正常逻辑写
事务里面加行锁 就行了 不用这么复杂 |
10
javalaw2010 347 天前 1
要么,你一条一条来,当某个 update 的的影响行数是 0 时,你 rollback ,要么,你有一个预期有多少行会受影响,如果实际影响的行数与预期不符,你 rollback 。异常这种东西一般发生在你代码里,跟数据库有什么关系。
|
11
nerkeler OP @jowan 更新的是多个产品记录,并不是一条记录,你这个思路要加表锁,比如 产品 1 减库存成功了,产品 2 减库存也成功了, 但是产品 3 不满足更新的条件,这时候需要把前两个更新操作回撤
|
12
nerkeler OP @javalaw2010 明白你的意思了,通过受影响的行数 判断,手动抛异常
|
14
Plutooo 347 天前
这不是一个代码里 @Transaction 就解决的事情吗,要么手动抛异常,要么手动回滚
|
15
nerkeler OP 学艺不精,谢了各位
|
16
jowan 347 天前
@Plutooo 他这个就是为了保证库存一致性的 并发不大的情况
@Transaction 后 可以按正常逻辑顺序来写 SQL 比如先减产产品库存表 查出来后 for update 加锁 再去加产品包表的库存 不需要 case when |
17
buxudashi 347 天前
事务开启;
结果=false; do{ 执行 1 成功往下走,不成功 break; 执行 2 成功往下走,不成功 break; ...... 结果=true; }while(false);//保证只执行 1 次。 如果 true commit; 如果 false callback; |
18
8355 347 天前
还好是 java 开发 如果是 php 的估计要被喷死了😀
|
20
xiaoHuaJia 347 天前
如果请求量不高就事务 。是如果是高并发场景 redis 加 lua 脚本
|
21
uleh 347 天前
看了标题我以为是海量数据分布式更新还要保障高并发
进来一看。。。 |
23
ZField 347 天前
库存问题啊,省事的方案就是提到 redis 上面来处理 ,缓存都处理完了再落库。
直接 MySQL 的话,单机就锁库存,然后开启事务,手动判断,手动回滚。 |
24
totoro52 347 天前
判断是不是更新条数 0 0 就直接抛异常不就好了 剩下的都不走了 然后交给分布式事务去处理即可。
|
25
jackaluo 347 天前
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; // 任何一个更新失败都会导致整个事务失败 } } } |
28
buxudashi 347 天前
@nerkeler 不能简化。你的 foreach 里会全部执行。比如执行 10 次,第 3 次失败。你第 4 次和后面的循环已经没意义。后面的 commit 更加没意义。
正常情况下要退出后后 fallback.或者集体 commit. |
29
siweipancc 347 天前 via iPhone
坏了,事务都没学,你没上大学?
|
31
nerkeler OP @siweipancc 你要和我探讨探讨机械原理?
|
32
luomao 346 天前
楼主快说你是开发 node 的
|
33
xwayway 346 天前
@siweipancc 所以不是说看不起非科班,而是非科班……。完了说这句话我要被喷死,但是我还是想说
|
34
shea 346 天前
try 再加事务,还好你是用的 java ,要是 php ,现在你这帖已经是热帖了。
|
35
cyrivlclth 346 天前
@xwayway 我非科班哈,这种基础知识只能说这行门槛太低了。
|
36
julyclyde 345 天前
按说不应该存在 affected 为 0 的情况吧?
是不是应该先 select for update 锁上然后再 update ? |