Skip to content

fix: 多租户时,菜单和角色对应保存主键冲突 - #217

Open
luoqiz wants to merge 1 commit into
continew-org:devfrom
luoqiz:fix-role-menu-relation
Open

fix: 多租户时,菜单和角色对应保存主键冲突#217
luoqiz wants to merge 1 commit into
continew-org:devfrom
luoqiz:fix-role-menu-relation

Conversation

@luoqiz

@luoqiz luoqiz commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

PR 类型

  • 新 feature
  • Bug 修复
  • 功能增强
  • 文档变更
  • 代码样式变更
  • 重构
  • 性能改进
  • 单元测试
  • CI/CD
  • 其他

PR 目的

解决方案

PR 测试

Changelog

模块 Changelog Related issues

其他信息

提交前确认

  • PR 代码经过了完整测试,并且通过了代码规范检查
  • 已经完整填写 Changelog,并链接到了相关 issues
  • PR 代码将要提交到 dev 分支

@Charles7c

Copy link
Copy Markdown
Member

代码评审:PR #217 多租户菜单-角色主键冲突修复

整体评价

修复方向完全正确。sys_menuignore-tables 中(菜单 ID 全局共享),而 sys_role_menu 受多租户插件管控(tenant_id 自动注入)。当不同租户共享同一套菜单、且复用跨租户角色(如 SUPER_ADMIN)时,原主键 (role_id, menu_id) 必然冲突。将 tenant_id 纳入主键是标准且正确的解法。改动精准、MySQL/PostgreSQL 双库一致,没有范围蔓延。

✅ 任务 1:是否还有类似的主键冲突问题?

sys_role_menu 是当前唯一存在该类问题的表,其余均安全。

主键 是否受租户管控 引用的共享实体 结论
sys_role_menu (role_id, menu_id) sys_menu(ignore-tables,全局菜单 ID) 🔴 冲突(本 PR 修复)
sys_role_dept (role_id, dept_id) sys_dept(租户隔离,CosID 全局唯一) ✅ 安全
sys_message_log (message_id, user_id) 两者均为 CosID 全局唯一 ✅ 安全
sys_notice_log (notice_id, user_id) 两者均为 CosID 全局唯一 ✅ 安全
tenant_package_menu (package_id, menu_id) 否(共享配置表) 套餐/菜单均全局 ✅ 安全

🔴 阻塞性问题(合并前必须修复)

1. 修改了已执行的 Liquibase 变更集,会导致存量库启动失败。 整个 plugin_tenant.sql 是单一变更集 小熊:1,本 PR 把 DROP/ADD PRIMARY KEY 追加进了这个已存在的变更集,而非新增独立变更集。任何已执行过 小熊:1 的环境(dev/staging/prod)再次启动时会因 checksum 不一致抛出 ValidationFailedException 并拒绝启动。建议改为新增独立变更集(MySQL/PostgreSQL 各加一个):

-- changeset luoqiz:2
-- comment 多租户:sys_role_menu 主键补充租户ID
ALTER TABLE `sys_role_menu` DROP PRIMARY KEY, ADD PRIMARY KEY (`tenant_id`, `role_id`, `menu_id`);

🟡 建议

2. 存量脏数据风险:若历史因该 bug 残留重复 (tenant_id, role_id, menu_id) 行,ADD PRIMARY KEY 会中断迁移。执行前先排查:SELECT tenant_id, role_id, menu_id, COUNT(*) c FROM sys_role_menu GROUP BY tenant_id, role_id, menu_id HAVING COUNT(*) > 1;
3. PR 描述几乎为空:建议补充根因与验证步骤(新建租户 → 分配菜单 → 切换租户再分配相同菜单不报 Duplicate entry)。
4. 建议补集成验证RoleMenuServiceImpl.add()removeinsertBatch 逻辑没问题,但最好有一次验证。

💭 小建议

5. 冗余索引:主键改为 (tenant_id, role_id, menu_id) 后,idx_tenant_id 单列索引已能被聚簇索引最左前缀覆盖,可顺手 DROP INDEX idx_tenant_id
6. PostgreSQL 约束名:建议用 DROP CONSTRAINT IF EXISTS "sys_role_menu_pkey" 更稳健。

总结

修复正确性 ✅;规范上 🔴 违反 Liquibase「不修改已执行变更集」约定(#1 是唯一硬阻塞)。修复方向无需质疑,核心是换个变更集落地方式即可合并。

将 sys_role_menu、sys_role_dept 主键及 sys_user_role 唯一索引调整为以 tenant_id 开头,适配行级租户查询,并去掉已覆盖的 idx_tenant_id。
@luoqiz
luoqiz force-pushed the fix-role-menu-relation branch from aef93da to 01f9007 Compare August 7, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants