Files
Friendship-and-chat-api/sql/mysql/recent/20261105_member_recent_cfg_unique.sql
dzc f55561c98d feat:上传到阿里云oss
feat:把以前的图片迁移到阿里云oss
2026-11-05 15:22:55 +08:00

71 lines
3.6 KiB
SQL

-- 修复重复朋友圈配置,并保证同一用户最多只有一条有效配置。
-- 适用 MySQL 5.7 / 8.0。执行前选择业务库,并备份 member_recent_cfg。
-- 先部署兼容重复数据/唯一键冲突的代码;执行期间暂停配置写入(登录初始化、隐私设置、后台编辑)。
-- DDL 会隐式提交;如中途失败,修复原因后可重跑,不能依靠 ROLLBACK 撤销整个脚本。
-- 只逻辑删除较旧行,不重建默认配置,不修改保留行的隐私/通知选项。
-- member_id 引用 member_user 的全局主键,唯一键不额外拼接可能为 NULL 的 tenant_id。
-- 预检:完整展示重复配置,便于核对 home_hide/global_hide/privacy_secure/short_note/is_push 等实际字段。
-- 保留顺序与服务查询一致:update_time 最新优先,时间相同取 id 最大;NULL 更新时间排在最后。
SELECT cfg.*
FROM `member_recent_cfg` cfg
INNER JOIN (
SELECT `member_id`, COUNT(*) AS active_count
FROM `member_recent_cfg`
WHERE `deleted` = b'0'
GROUP BY `member_id`
HAVING COUNT(*) > 1
) duplicated ON duplicated.`member_id` = cfg.`member_id`
WHERE cfg.`deleted` = b'0'
ORDER BY cfg.`member_id`, cfg.`update_time` DESC, cfg.`id` DESC;
-- 先物化待删除 id,再更新,避免修改 update_time 影响同一批次的保留顺序。
-- GROUP BY 阻止 MySQL 5.7/8 合并派生表,避免 1093 自查询更新错误。
UPDATE `member_recent_cfg` obsolete
INNER JOIN (
SELECT older.`id`
FROM `member_recent_cfg` older
INNER JOIN `member_recent_cfg` newer
ON newer.`member_id` = older.`member_id`
AND newer.`deleted` = b'0'
AND (
newer.`update_time` > older.`update_time`
OR (older.`update_time` IS NULL AND newer.`update_time` IS NOT NULL)
OR (newer.`update_time` <=> older.`update_time` AND newer.`id` > older.`id`)
)
WHERE older.`deleted` = b'0'
GROUP BY older.`id`
) duplicate_ids ON duplicate_ids.`id` = obsolete.`id`
SET obsolete.`deleted` = b'1', obsolete.`update_time` = CURRENT_TIMESTAMP
WHERE obsolete.`deleted` = b'0';
SELECT ROW_COUNT() AS logically_deleted_duplicate_configs;
-- 已删除行生成 NULL,保留所有删除历史,同时允许以后重新创建配置。
SET @cfg_add_column_sql = IF(
(SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'member_recent_cfg' AND COLUMN_NAME = 'active_unique_flag') = 0,
'ALTER TABLE `member_recent_cfg` ADD COLUMN `active_unique_flag` tinyint GENERATED ALWAYS AS (CASE WHEN `deleted` = 0 THEN 1 ELSE NULL END) STORED COMMENT ''有效配置唯一标记,删除记录为NULL''',
'SELECT ''active_unique_flag already exists'' AS migration_step'
);
PREPARE cfg_stmt FROM @cfg_add_column_sql;
EXECUTE cfg_stmt;
DEALLOCATE PREPARE cfg_stmt;
SET @cfg_add_index_sql = IF(
(SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'member_recent_cfg' AND INDEX_NAME = 'uk_member_recent_cfg_active') = 0,
'ALTER TABLE `member_recent_cfg` ADD UNIQUE KEY `uk_member_recent_cfg_active` (`member_id`, `active_unique_flag`)',
'SELECT ''uk_member_recent_cfg_active already exists'' AS migration_step'
);
PREPARE cfg_stmt FROM @cfg_add_index_sql;
EXECUTE cfg_stmt;
DEALLOCATE PREPARE cfg_stmt;
-- 验收:应无重复分组;索引 NON_UNIQUE 应为 0。
SELECT `member_id`, COUNT(*) AS active_count
FROM `member_recent_cfg`
WHERE `deleted` = b'0'
GROUP BY `member_id`
HAVING COUNT(*) > 1;
SHOW INDEX FROM `member_recent_cfg` WHERE Key_name = 'uk_member_recent_cfg_active';