-- 2026_07_21_003_exhibition_hours_idempotent.sql -- 批次1.2:累计时长幂等(用户级 + 资产级) -- 执行前请先备份: -- pg_dump -h -U postgres -t exhibition_hours_log -t asset_exhibition_hours_log > backup_1_2.sql -- 触发场景:fan_profile_repository.AddExhibitionHours/assetLevelService.AddExhibitionHours -- 重复调用会造成 total_exhibition_hours / season_exhibition_hours 多次叠加 -- 设计:每条幂等键由 source_id 唯一约束保证,INSERT ON CONFLICT DO NOTHING 即跳过 BEGIN; -- (1) 用户级幂等 log CREATE TABLE IF NOT EXISTS exhibition_hours_log ( id BIGINT PRIMARY KEY, source_id VARCHAR(100) NOT NULL UNIQUE, user_id BIGINT NOT NULL, star_id BIGINT NOT NULL, hours BIGINT NOT NULL, created_at BIGINT NOT NULL ); CREATE INDEX IF NOT EXISTS ix_exh_log_user_star ON exhibition_hours_log (user_id, star_id); CREATE INDEX IF NOT EXISTS ix_exh_log_created ON exhibition_hours_log (created_at); -- (2) 资产级幂等 log CREATE TABLE IF NOT EXISTS asset_exhibition_hours_log ( id BIGINT PRIMARY KEY, source_id VARCHAR(100) NOT NULL UNIQUE, asset_id BIGINT NOT NULL, hours INT NOT NULL, created_at BIGINT NOT NULL ); CREATE INDEX IF NOT EXISTS ix_asset_exh_log_asset ON asset_exhibition_hours_log (asset_id); -- (3) 序列同步(CLAUDE.md 强制;新表无现存行,序列置 1) -- 内部去重 log 表无脚本硬编码其 id,不适用 START 10000 约定;序列从 1 起步。 CREATE SEQUENCE IF NOT EXISTS exhibition_hours_log_id_seq OWNED BY exhibition_hours_log.id; ALTER TABLE exhibition_hours_log ALTER COLUMN id SET DEFAULT nextval('exhibition_hours_log_id_seq'); SELECT setval('exhibition_hours_log_id_seq', GREATEST((SELECT COALESCE(MAX(id),0) FROM exhibition_hours_log), 1)); CREATE SEQUENCE IF NOT EXISTS asset_exhibition_hours_log_id_seq OWNED BY asset_exhibition_hours_log.id; ALTER TABLE asset_exhibition_hours_log ALTER COLUMN id SET DEFAULT nextval('asset_exhibition_hours_log_id_seq'); SELECT setval('asset_exhibition_hours_log_id_seq', GREATEST((SELECT COALESCE(MAX(id),0) FROM asset_exhibition_hours_log), 1)); COMMIT;