From bdac4ab7b2f67c151ebf4661a65b85be604cc379 Mon Sep 17 00:00:00 2001 From: huang Date: Sat, 28 Mar 2026 10:38:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(fin):=20=E6=BF=80=E6=B4=BB=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=B9=B6=E5=8F=91=E8=A1=8C=E9=94=81=E4=BF=9D=E6=8A=A4?= =?UTF-8?q?=20FIN-03?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - commission_withdrawal_setting/service.go: 激活事务内首步加 FOR UPDATE 行锁,防止并发时出现多条 is_active=true - wechat_config_store.go: ActivateInTx 激活前同样加行锁保护 --- internal/service/commission_withdrawal_setting/service.go | 7 +++++++ internal/store/postgres/wechat_config_store.go | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/internal/service/commission_withdrawal_setting/service.go b/internal/service/commission_withdrawal_setting/service.go index 21eb35a..6cac726 100644 --- a/internal/service/commission_withdrawal_setting/service.go +++ b/internal/service/commission_withdrawal_setting/service.go @@ -11,6 +11,7 @@ import ( "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" "gorm.io/gorm" + "gorm.io/gorm/clause" ) type Service struct { @@ -47,6 +48,12 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateWithdrawalSettingRe setting.Updater = currentUserID err := s.db.Transaction(func(tx *gorm.DB) error { + // 先锁定当前活跃记录,防止并发激活导致多条 is_active=true + var current model.CommissionWithdrawalSetting + tx.WithContext(ctx).Clauses(clause.Locking{Strength: "UPDATE"}). + Where("is_active = ?", true). + First(¤t) + if err := s.commissionWithdrawalSettingStore.DeactivateCurrentWithTx(ctx, tx); err != nil { return errors.Wrap(errors.CodeInternalError, err, "失效旧配置失败") } diff --git a/internal/store/postgres/wechat_config_store.go b/internal/store/postgres/wechat_config_store.go index cef0500..f85b618 100644 --- a/internal/store/postgres/wechat_config_store.go +++ b/internal/store/postgres/wechat_config_store.go @@ -7,6 +7,7 @@ import ( "github.com/break/junhong_cmp_fiber/internal/store" "github.com/redis/go-redis/v9" "gorm.io/gorm" + "gorm.io/gorm/clause" ) // WechatConfigStore 微信参数配置数据访问层 @@ -100,6 +101,12 @@ func (s *WechatConfigStore) GetActive(ctx context.Context) (*model.WechatConfig, // ActivateInTx 在事务内激活指定配置(先停用所有,再激活指定记录) func (s *WechatConfigStore) ActivateInTx(ctx context.Context, tx *gorm.DB, id uint) error { + // 先锁定当前活跃记录,防止并发激活导致多条 is_active=true + var current model.WechatConfig + tx.WithContext(ctx).Clauses(clause.Locking{Strength: "UPDATE"}). + Where("is_active = ?", true). + First(¤t) + // 先停用所有激活的配置 if err := tx.WithContext(ctx).Model(&model.WechatConfig{}). Where("is_active = ?", true).