迁移:新增业务菜单层级补丁

This commit is contained in:
焦龙言
2026-07-27 21:02:48 +08:00
parent db5755586d
commit a1613f8780
2 changed files with 408 additions and 0 deletions
@@ -0,0 +1,156 @@
-- 本文件是人工执行的 MySQL 前向补丁,未自动执行。
-- 执行前备份数据库,并在维护窗口使用独立连接运行标准 mysql batch。
-- 旧状态和目标状态均可通过写前校验,因此本补丁可幂等重跑。
-- 标准 mysql batch 遇错后必须退出并关闭连接,使未提交事务回滚;禁止使用 mysql --force。
-- 在事务外准备六个固定菜单的稳定身份及完整旧/新层级状态。
drop temporary table if exists promote_business_menus_expected;
create temporary table promote_business_menus_expected (
menu_id bigint not null,
menu_name varchar(50) not null,
path varchar(200),
component varchar(255),
query varchar(255),
route_name varchar(50),
is_frame int,
is_cache int,
menu_type char(1),
visible char(1),
status char(1),
perms varchar(100),
icon varchar(100),
old_parent_id bigint not null,
old_order_num int not null,
new_parent_id bigint not null,
new_order_num int not null,
primary key (menu_id)
) engine=innodb;
insert into promote_business_menus_expected (
menu_id, menu_name, path, component, query, route_name,
is_frame, is_cache, menu_type, visible, status, perms, icon,
old_parent_id, old_order_num, new_parent_id, new_order_num
) values
(1, '系统管理', 'system', null, '', '', 1, 0, 'M', '0', '0', '', 'system', 0, 1, 0, 4),
(2, '系统监控', 'monitor', null, '', '', 1, 0, 'M', '0', '0', '', 'monitor', 0, 2, 0, 5),
(3, '系统工具', 'tool', null, '', '', 1, 0, 'M', '0', '0', '', 'tool', 0, 3, 0, 6),
(121, '基础资料维护', 'businessMaster', null, '', '', 1, 0, 'M', '0', '0', '', '#', 1, 10, 0, 1),
(122, '业务管理', 'businessOperation', null, '', '', 1, 0, 'M', '0', '0', '', '#', 1, 11, 0, 2),
(123, '报表查询', 'businessReport', null, '', '', 1, 0, 'M', '0', '0', '', '#', 1, 12, 0, 3);
drop temporary table if exists promote_business_menus_guard;
create temporary table promote_business_menus_guard (
guard_token varchar(64) not null,
primary key (guard_token)
) engine=innodb;
start transaction;
-- 锁定六个固定 ID,防止身份预检与永久更新之间被并发修改。
select menu_id
from sys_menu
where menu_id in (1, 2, 3, 121, 122, 123)
order by menu_id
for update;
-- 写前只接受六行全部处于旧状态或全部处于目标状态。
-- 缺行、稳定身份漂移或新旧状态混合时,重复主键 token 会中止 batch。
insert into promote_business_menus_guard (guard_token)
select guard_token
from (
select 'promote-business-menus-precondition-conflict' as guard_token
union all
select if(
count(actual.menu_id) = 6
and sum(
(binary actual.menu_name <=> binary expected.menu_name)
and (binary actual.path <=> binary expected.path)
and (binary actual.component <=> binary expected.component)
and (binary actual.query <=> binary expected.query)
and (binary actual.route_name <=> binary expected.route_name)
and (actual.is_frame <=> expected.is_frame)
and (actual.is_cache <=> expected.is_cache)
and (binary actual.menu_type <=> binary expected.menu_type)
and (binary actual.visible <=> binary expected.visible)
and (binary actual.status <=> binary expected.status)
and (binary actual.perms <=> binary expected.perms)
and (binary actual.icon <=> binary expected.icon)
) = 6
and (
sum(
(actual.parent_id <=> expected.old_parent_id)
and (actual.order_num <=> expected.old_order_num)
) = 6
or sum(
(actual.parent_id <=> expected.new_parent_id)
and (actual.order_num <=> expected.new_order_num)
) = 6
),
'promote-business-menus-precondition-verified',
'promote-business-menus-precondition-conflict'
) as guard_token
from promote_business_menus_expected as expected
left join sys_menu as actual
on actual.menu_id = expected.menu_id
) as precondition_guard_rows;
-- 唯一永久 DML:只更新六个固定菜单的父级和显示顺序。
update sys_menu
set parent_id = case
when menu_id in (121, 122, 123) then 0
else parent_id
end,
order_num = case menu_id
when 121 then 1
when 122 then 2
when 123 then 3
when 1 then 4
when 2 then 5
when 3 then 6
else order_num
end
where menu_id in (1, 2, 3, 121, 122, 123);
-- 提交前再次核对六行稳定身份及完整目标状态。
insert into promote_business_menus_guard (guard_token)
select guard_token
from (
select 'promote-business-menus-postcondition-conflict' as guard_token
union all
select if(
count(actual.menu_id) = 6
and sum(
(binary actual.menu_name <=> binary expected.menu_name)
and (binary actual.path <=> binary expected.path)
and (binary actual.component <=> binary expected.component)
and (binary actual.query <=> binary expected.query)
and (binary actual.route_name <=> binary expected.route_name)
and (actual.is_frame <=> expected.is_frame)
and (actual.is_cache <=> expected.is_cache)
and (binary actual.menu_type <=> binary expected.menu_type)
and (binary actual.visible <=> binary expected.visible)
and (binary actual.status <=> binary expected.status)
and (binary actual.perms <=> binary expected.perms)
and (binary actual.icon <=> binary expected.icon)
) = 6
and sum(
(actual.parent_id <=> expected.new_parent_id)
and (actual.order_num <=> expected.new_order_num)
) = 6,
'promote-business-menus-postcondition-verified',
'promote-business-menus-postcondition-conflict'
) as guard_token
from promote_business_menus_expected as expected
left join sys_menu as actual
on actual.menu_id = expected.menu_id
) as postcondition_guard_rows;
commit;
drop temporary table promote_business_menus_guard;
drop temporary table promote_business_menus_expected;
select menu_id, menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms
from sys_menu
where menu_id in (1, 2, 3, 121, 122, 123)
order by order_num, menu_id;