93 lines
4.0 KiB
SQL
93 lines
4.0 KiB
SQL
-- =============================================================================
|
||
-- app_icon 版本号 / 生效状态 存量数据修复脚本
|
||
--
|
||
-- 背景:
|
||
-- 旧逻辑用「当前生效版本 + 1」生成版本号,无当前生效记录时固定用 1;
|
||
-- 而删除是逻辑删除(is_deleted=1),且唯一索引 uk_package_version(package_name, version)
|
||
-- 不包含 is_deleted。当前生效记录被删除或缺失时,再次上传就会撞唯一键:
|
||
-- Duplicate entry 'com_alibaba_android_rimet-1' for key 'app_icon.uk_package_version'
|
||
--
|
||
-- 新逻辑:
|
||
-- version = 该 package_name 下所有记录(含 is_deleted=1)的 MAX(version) + 1,
|
||
-- 版本号只增不减、永不复用;上传 / 锁定已按包名加锁并置于同一事务内。
|
||
--
|
||
-- 使用说明:
|
||
-- 1. 本脚本仅用于「已在运行、不重建表」的库;全新部署执行 app_icon.sql 即可。
|
||
-- 2. 由 DBA 在业务低峰期单独执行,执行前请备份 app_icon 表。
|
||
-- 3. 诊断语句(第 1 ~ 3 段)先执行确认现状,再执行修复语句(第 4 ~ 5 段)。
|
||
-- =============================================================================
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 1. 诊断:同一包名存在多条 status=1(会导致 one() 抛 TooManyResultsException)
|
||
-- -----------------------------------------------------------------------------
|
||
SELECT package_name, COUNT(*) AS active_cnt
|
||
FROM app_icon
|
||
WHERE is_deleted = 0
|
||
AND status = 1
|
||
GROUP BY package_name
|
||
HAVING COUNT(*) > 1;
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 2. 诊断:同一包名有未删除记录,但没有任何 status=1(上传会走「无当前版本」分支)
|
||
-- -----------------------------------------------------------------------------
|
||
SELECT package_name, COUNT(*) AS alive_cnt, MAX(version) AS max_version
|
||
FROM app_icon
|
||
WHERE is_deleted = 0
|
||
GROUP BY package_name
|
||
HAVING SUM(status = 1) = 0;
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 3. 诊断:查看具体包名的版本与删除残留
|
||
-- -----------------------------------------------------------------------------
|
||
SELECT id, package_name, version, status, locked, is_deleted, update_time
|
||
FROM app_icon
|
||
WHERE package_name = 'com_alibaba_android_rimet'
|
||
ORDER BY is_deleted, version;
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 4. 修复多条 status=1:保留 version 最大的一条为当前生效,其余置为历史
|
||
-- -----------------------------------------------------------------------------
|
||
UPDATE app_icon a
|
||
JOIN (SELECT package_name, MAX(version) AS max_version
|
||
FROM app_icon
|
||
WHERE is_deleted = 0
|
||
AND status = 1
|
||
GROUP BY package_name) t
|
||
ON a.package_name = t.package_name
|
||
SET a.status = 0,
|
||
a.update_time = NOW()
|
||
WHERE a.is_deleted = 0
|
||
AND a.status = 1
|
||
AND a.version < t.max_version;
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 5. 修复无 status=1:把未删除记录里版本号最大的一条置为当前生效
|
||
-- -----------------------------------------------------------------------------
|
||
UPDATE app_icon a
|
||
JOIN (SELECT package_name, MAX(version) AS max_version
|
||
FROM app_icon
|
||
WHERE is_deleted = 0
|
||
GROUP BY package_name
|
||
HAVING SUM(status = 1) = 0) t
|
||
ON a.package_name = t.package_name
|
||
AND a.version = t.max_version
|
||
SET a.status = 1,
|
||
a.update_time = NOW()
|
||
WHERE a.is_deleted = 0;
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 6. 复核:两条诊断语句均应返回空结果集
|
||
-- -----------------------------------------------------------------------------
|
||
SELECT package_name, COUNT(*) AS active_cnt
|
||
FROM app_icon
|
||
WHERE is_deleted = 0
|
||
AND status = 1
|
||
GROUP BY package_name
|
||
HAVING COUNT(*) > 1;
|
||
|
||
SELECT package_name, COUNT(*) AS alive_cnt
|
||
FROM app_icon
|
||
WHERE is_deleted = 0
|
||
GROUP BY package_name
|
||
HAVING SUM(status = 1) = 0;
|