SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; USE hyapp_lucky_gift; -- 每列独立探测,使迁移在“全新库、004 后旧库、曾执行一半的旧库”上都可重复运行。 -- 人工资金必须与正常送礼入池/返奖分账,不能污染 total_in/total_out 的 RTP 经营口径。 SET @ddl := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'lucky_pools' AND COLUMN_NAME = 'manual_credit_total') = 0, 'ALTER TABLE lucky_pools ADD COLUMN manual_credit_total BIGINT NOT NULL DEFAULT 0 COMMENT ''累计人工注资金币,不计入业务 total_in'' AFTER total_out', 'SELECT 1'); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @ddl := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'lucky_pools' AND COLUMN_NAME = 'manual_debit_total') = 0, 'ALTER TABLE lucky_pools ADD COLUMN manual_debit_total BIGINT NOT NULL DEFAULT 0 COMMENT ''累计人工扣资金币,不计入业务 total_out'' AFTER manual_credit_total', 'SELECT 1'); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; CREATE TABLE IF NOT EXISTS lucky_pool_adjustments ( app_code VARCHAR(32) NOT NULL COMMENT '应用编码', adjustment_id VARCHAR(128) NOT NULL COMMENT '调用方资金幂等 ID', pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', strategy_version VARCHAR(32) NOT NULL COMMENT 'fixed_v2/dynamic_v3', scope_type VARCHAR(32) NOT NULL COMMENT '实际资金账本 scope_type', direction VARCHAR(16) NOT NULL COMMENT 'in/out', amount_coins BIGINT NOT NULL COMMENT '本次人工调整金币', reason VARCHAR(512) NOT NULL COMMENT '管理员填写的调整原因', operator_admin_id BIGINT NOT NULL COMMENT '操作管理员 ID', request_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '链路 request_id,不作为幂等键', insert_token VARCHAR(64) NOT NULL COMMENT '首次插入事务随机令牌,用于并发幂等判定', balance_before BIGINT NOT NULL DEFAULT 0 COMMENT '首次应用前余额', balance_after BIGINT NOT NULL DEFAULT 0 COMMENT '首次应用后余额', pool_snapshot_json JSON NULL COMMENT '首次应用后的完整奖池快照,供幂等重放', status VARCHAR(16) NOT NULL DEFAULT 'pending' COMMENT 'pending/applied', created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', PRIMARY KEY (app_code, adjustment_id), KEY idx_lucky_pool_adjustments_pool (app_code, pool_id, strategy_version, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物人工奖池调整事实'; SET @ddl := IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'lucky_pool_adjustments' AND COLUMN_NAME = 'insert_token') = 0, 'ALTER TABLE lucky_pool_adjustments ADD COLUMN insert_token VARCHAR(64) NOT NULL DEFAULT '''' COMMENT ''首次插入事务随机令牌,用于并发幂等判定'' AFTER request_id', 'SELECT 1'); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 只看每个 app+pool 当前最新不可变版本。若它已经切换到 dynamic_v3,就创建一口独立的零余额账本; -- ON DUPLICATE 分支绝不更新余额、累计或时间,迁移重跑以及后续 V3 版本都不会重置真实资金。 INSERT INTO lucky_pools ( app_code, scope_type, scope_id, balance, reserve_floor, total_in, total_out, manual_credit_total, manual_debit_total, profit_total, anchor_income_total, initial_seed_total, created_at_ms, updated_at_ms ) SELECT current_rule.app_code, 'pool_dynamic_v3', current_rule.pool_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, current_rule.created_at_ms, current_rule.created_at_ms FROM lucky_gift_rule_versions current_rule INNER JOIN ( SELECT app_code, pool_id, MAX(rule_version) AS rule_version FROM lucky_gift_rule_versions GROUP BY app_code, pool_id ) latest ON latest.app_code = current_rule.app_code AND latest.pool_id = current_rule.pool_id AND latest.rule_version = current_rule.rule_version WHERE current_rule.strategy_version = 'dynamic_v3' ON DUPLICATE KEY UPDATE scope_id = lucky_pools.scope_id;