fix(借库扫码出库): 撤销 joinedload 修复 PG "FOR UPDATE cannot be applied to nullable side of outer join"
- 83b3db6 引入的 joinedload(ModelClass.base) 触发 LEFT OUTER JOIN,
而 with_for_update() 会被 SQLAlchemy 透传到 join 的 nullable 侧,
PG 直接抛 FeatureNotSupported,且连表加锁有死锁风险
- 退回最安全的单表 FOR UPDATE 模式,接受 N+1 lazy 加载的代价
- 在 防线3 上方加防回归注释,明确禁止未来再加 joinedload
- process_return 中的另两处 joinedload 不带 FOR UPDATE,不受 PG 限制,保留
This commit is contained in:
@ -95,8 +95,11 @@ class TransService:
|
||||
|
||||
# ==============================================
|
||||
# ★ 防线3:并发超卖与负库存 - 锁行后再查可用库存
|
||||
# ⚠️ 不要在此加 joinedload(ModelClass.base)!PG 禁止 FOR UPDATE
|
||||
# 应用到 outer join 的 nullable 侧,会报 FeatureNotSupported
|
||||
# 并有死锁风险。stock.base 走单条 lazy 加载是已知取舍。
|
||||
# ==============================================
|
||||
stock = ModelClass.query.options(joinedload(ModelClass.base)).with_for_update().get(stock_id)
|
||||
stock = ModelClass.query.with_for_update().get(stock_id)
|
||||
if not stock: raise ValueError(f"库存不存在 ID:{stock_id}")
|
||||
|
||||
# ==============================================
|
||||
|
||||
Reference in New Issue
Block a user