db := database.GetDB(ctx)
func (a *RuleTarget) DelSystemRuleTargets(
ctx context.Context,
targets []*pbWeb.RuleTarget,
) (successCount int32, err error) {
for _, target := range targets {
// 注意如果是uid层面的删除,要级联删除cid和aid的数据
if fflag.IsSwitchOn(ctx, fflag.FlagSystemRuleAllRalated) {
log.ErrorContextf(ctx, "begin delete")
db = db.Where("rule_id = ?", 0).Where("account_id = ?", target.AccountId).
Where("status = ?", 0)
if target.CampaignId != 0 {
// 对cid进行删除
db = db.Where("campaign_id = ?", target.CampaignId)
}
err = db.Delete(RuleTarget{}).Error
} else {
err = db.Where(map[string]interface{}{
"rule_id": 0,
"account_id": target.AccountId,
"campaign_id": target.CampaignId,
"adgroup_id": target.AdgroupId,
}).Delete(RuleTarget{}).Error
}
if err != nil {
log.ErrorContextf(ctx, "RuleTarget.DelSystemRuleTargets() Error: %s", err.Error())
continue
} else {
successCount++
}
}
return successCount, nil
}
这里db = xx 语句执行了多次,因此这里gorm将查询条件放在了db中。结果就是在循环中下次执行的时候,db中的数据并没有清除掉。带上了上次的执行条件。例如:
第一次:
UPDATE `rule_targets` SET `deleted_at`='2021-05-24 15:57:32' WHERE `rule_targets`.`deleted_at` IS NULL AND ((rule_id = 0) AND (account_id = 172198) AND (status = 0))
第二次:
UPDATE `rule_targets` SET `deleted_at`='2021-05-24 15:57:32' WHERE `rule_targets`.`deleted_at` IS NULL AND ((rule_id = 0) AND (account_id = 172198) AND (status = 0) AND (rule_id = 0) AND (account_id = 20458) AND (status = 0))
但是这么写就可以:
// 开启保护中状态
// 因为存在批量操作,这里对非一键托管状态的aid忽略掉
func (a *RuleTarget) OpenSystemRuleProtected(ctx context.Context, targets []*pbWeb.RuleTarget) int {
// aid开启保护中,先删除,后增加这条记录(status = -1)
successCount := 0
systemRuleTargetsmap, err := a.getAidSystemRuleTarget(ctx, targets)
if err != nil {
log.ErrorContextf(ctx, "err in OpenSystemRuleProtected call getAidSystemRuleTarget:%v", err)
return successCount
}
db := database.GetDB(ctx)
for _, target := range targets {
// 不属于一键托管中
if systemRuleTargetsmap[target.AdgroupId] == 0 {
successCount++
continue
}
log.ErrorContextf(ctx, "begin delete")
err := db.Where(map[string]interface{}{
"rule_id": 0,
"account_id": target.AccountId,
"campaign_id": target.CampaignId,
"adgroup_id": target.AdgroupId,
}).Delete(RuleTarget{}).Error
if err != nil {
log.ErrorContextf(ctx, "del rule_target[%v]err:%v", target, err)
continue
}
// ruleTargetModel := &RuleTarget{
// RuleID: 0,
// AccountID: target.AccountId,
// CampaignID: target.CampaignId,
// AdGroupID: target.AdgroupId,
// Status: -1,
// }
// ruleTargetModel.setInstance(ruleTargetModel)
// err = ruleTargetModel.Save(ctx)
// if err != nil {
// log.ErrorContextf(ctx, "del rule_target[%v]err:%v", target, err)
// continue
// }
successCount++
}
return successCount
}
虽然也是在一个循环中执行同一个db变量,但是因为没有db = db.xxx语句,没有将ctx中放入查询条件,因此,每次循环执行是正常的额
实际修复方案:
for _, target := range targets {
db := database.GetDB(ctx)
// 注意如果是uid层面的删除,要级联删除cid和aid的数据
if fflag.IsSwitchOn(ctx, fflag.FlagSystemRuleAllRalated) {
db = db.Where("rule_id = ?", 0).Where("account_id = ?", target.AccountId).
Where("status = ?", 0)
if target.CampaignId != 0 {
// 对cid进行删除
db = db.Where("campaign_id = ?", target.CampaignId)
}
err = db.Delete(RuleTarget{}).Error
} else {
err = db.Where(map[string]interface{}{
"rule_id": 0,
"account_id": target.AccountId,
"campaign_id": target.CampaignId,
"adgroup_id": target.AdgroupId,
}).Delete(RuleTarget{}).Error
}
if err != nil {
log.ErrorContextf(ctx, "RuleTarget.DelSystemRuleTargets() Error: %s", err.Error())
continue
} else {
successCount++
}
}
就是吧 db := database.GetDB(ctx)放到循环内