修复:coupon_claim_event 回填按 (trace_id, coupon_id) 去重,避免上线迁移唯一约束冲突 (#172)
旧回填 INSERT ... SELECT 从 coupon_claim_record 整表 1:1 复制进 coupon_claim_event。 两表唯一键不同:源表按 (device_id, coupon_id, claim_date) 去重,trace_id 可空且不在 唯一键里;新表按 (trace_id, coupon_id) 唯一。一次会话的 /step 帧跨零点(Asia/Shanghai) 时,同一 (trace_id, coupon_id) 会落在相邻两天两行,复制时撞 uq_coupon_claim_event_trace_coupon, 整个迁移事务回滚,线上发车中断(线上命中 (1581db0e..., mt_banjia_zhoumo))。 回填改为按 (trace_id, coupon_id) 只取 id 最大(最近写入)的一行,SQLite/PostgreSQL 通用。 运行期写入路径(record_claims 按 (trace_id, coupon_id) upsert)本就无重复,仅此一次性回填未做防御。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: guke <guke@autohome.com.cn> Reviewed-on: #172
This commit was merged in pull request #172.
This commit is contained in:
@@ -69,7 +69,11 @@ def upgrade() -> None:
|
||||
unique=False,
|
||||
)
|
||||
|
||||
# 旧表只能回填当前仍保留的 trace;历史上已被每日去重覆盖的关联无法恢复。
|
||||
# 旧表按 (device, coupon, 自然日) 去重,trace_id 可空且不在唯一键里:同一
|
||||
# (trace_id, coupon_id) 可能散落在多行(如一次会话的 /step 帧跨零点,把同一张券
|
||||
# 写进相邻两天)。新表按 (trace_id, coupon_id) 唯一,整表 1:1 复制会撞
|
||||
# uq_coupon_claim_event_trace_coupon。回填时按 (trace_id, coupon_id) 只取 id 最大
|
||||
# (最近写入)的一行。历史上已被每日去重覆盖的关联仍无法恢复。
|
||||
op.execute(
|
||||
"""
|
||||
INSERT INTO coupon_claim_event (
|
||||
@@ -81,6 +85,12 @@ def upgrade() -> None:
|
||||
vendor, coupon_name, claimed_count, reason, extra, created_at, updated_at
|
||||
FROM coupon_claim_record
|
||||
WHERE trace_id IS NOT NULL
|
||||
AND id IN (
|
||||
SELECT MAX(id)
|
||||
FROM coupon_claim_record
|
||||
WHERE trace_id IS NOT NULL
|
||||
GROUP BY trace_id, coupon_id
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user