-- 02157 抽奖发奖账本(PR B) -- -- 目的:以 external_ref 作为 DB 层唯一键,做每个 draw 的发奖幂等。 -- 各 PrizeHandler.Dispatch 内先 SELECT/INSERT lottery_grant_ledger,命中即幂等返回, -- 未命中再调下游发放(UpdateSubscribe / UpdateCommission + WriteCommissionLog), -- 全部在同一 tx 内完成 → 抽奖事务与发奖账本同生共死。 -- -- 关键唯一索引:external_ref。惯例值 = "lottery:{activity_id}:{draw_id}"。 -- handler_type:与 lottery_prize.type 一致(vpn_duration / commission / …),用于统计。 CREATE TABLE IF NOT EXISTS `lottery_grant_ledger` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `external_ref` VARCHAR(128) NOT NULL COMMENT '幂等键:lottery:{activity_id}:{draw_id}', `handler_type` VARCHAR(32) NOT NULL COMMENT 'handler 类型,与 lottery_prize.type 对齐', `user_id` BIGINT UNSIGNED NOT NULL COMMENT '发放对象用户 ID(家庭组已归位到 owner)', `activity_id` BIGINT UNSIGNED NOT NULL COMMENT '活动 ID', `draw_id` BIGINT UNSIGNED NOT NULL COMMENT '抽奖记录 ID', `amount` BIGINT NOT NULL DEFAULT 0 COMMENT '发放数量(天/佣金金额,单位与 handler 一致)', `payload` JSON COMMENT '发放后的关键结果快照(订阅 ID、佣金前后余额等)', `granted_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '发放完成时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_external_ref` (`external_ref`), KEY `idx_user_activity` (`user_id`, `activity_id`), KEY `idx_draw_id` (`draw_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='抽奖发奖账本(幂等键 = external_ref)';