切片 5 — 扩展:每客户 SQL 覆盖
元数据驱动框架能表达的内容是有限的。
客户可能需要销售对账报表使用不同聚合规则,需要一个独特的自定义视图支撑成本看板,或需要一个行为从根本上偏离标准的存储过程。覆盖表(切片 4)可以加字段和覆盖 SQL 片段,但不能替换存储过程的逻辑;过程是代码,不是数据。
到达这个边界时,xly 的逃生口是:把手写 SQL 文件提交到 script/客户/<customer-name>/,并直接应用到该客户 schema。这完全绕过元数据层。它是生产中真实使用的通道,适用于若干客户;Wiki 必须诚实记录其范围、成本、适用时机和运维纪律。
记录对象
| 客户 | 重庆展印 |
| 覆盖文件 |
script/客户/重庆展印/Sp_SalSalesCheck.sql(723 行) |
| 替换内容 | 标准 Sp_SalSalesCheck 存储过程(销售对账列表) |
| 配套文件 |
script/客户/重庆展印/viw_salsaleschecking_pro.sql(该过程读取的自定义视图) |
| 部署 | 手工,由工程师 / DBA 对该客户 schema 应用 |
文件开头两行说明了这个通道的形状:
DROP PROCEDURE IF EXISTS `Sp_SalSalesCheck`;
delimiter ;;
CREATE PROCEDURE `Sp_SalSalesCheck`(IN sLoginId varchar(100), ...)
标准过程被 drop,自定义过程取而代之。gdsmodule 中的元数据仍按名称引用该过程(sProcName = 'Sp_SalSalesCheck');运行时照常调用。差异完全存在于过程主体中,而主体现在是工程师编写的变体。
当前代码库中有覆盖的客户
script/客户/ 下有 18 个客户子目录:
统兴 重庆展印 嘉诚 安徽金印 万昌
无锡中江 扬州浩宇 金九 亚明威 快马
金宣发 千彩 高旺 朝阳 上海亚峰
湛江新澳 福雅 远传
每个目录有一到十几个 .sql 文件。多数是自定义过程(Sp_*)和自定义视图(viw_*)。读取目录列表本身就是系统文档:这里的客户和功能,是框架无法表达、需要 bespoke 行为的地方。
覆盖如何进入系统
没有自动通道。搜索 Java 代码中加载 script/客户 或遍历这些目录的部署服务,没有结果。机制是运维性的:
- 工程师以标准过程为起点编写覆盖
.sql并修改主体。 - 文件提交到
script/客户/<customer>/,用于可追溯性。 - 使用
mysql --defaults-file=... < the-file.sql或等价方式,手工对目标客户 MySQL schema 执行。 - 从那以后,该客户 schema 中的过程主体就不同于其他客户;框架代码不变。
把文件放在代码库中很重要:工程团队可以一眼看出哪些客户偏离标准。但这不表示这些文件会作为任何 build 的一部分发布。
为什么这不同于切片 4
切片 4 的 gdsconfigformcustomslave 和切片 1 的元数据 Add/Update 路径都留在框架内部。客户特定行为是叠加在共享代码库之上:每个租户运行时读取相同 Java、相同 MyBatis mapper、相同标准过程。
切片 5 的通道位于框架之下。客户 schema 中有一个同名但主体不同的存储过程。调用 Sp_SalSalesCheck 的 Java / MyBatis 代码不知道另一端是标准过程还是重庆展印变体。框架不知道,也无法分辨。
因此覆盖具有:
- 强能力。 MySQL 存储过程 SQL 能写出的任何东西,都可替换标准行为。
- 运维脆弱。 客户 schema 重建、恢复或迁移时,覆盖必须重新应用或保持存活。它不跟随代码库备份,只跟随数据库备份。
-
推理困难。 维护人员读标准
Sp_SalSalesCheck源码时,必须记得某些客户实时 DB 上同名过程是另一段代码。stack trace 和“这个过程做什么”取决于你连到哪个 schema。
经验规则:优先选择切片 4 的元数据定制。只有元数据模型确实无法表达客户需求时,才使用切片 5 SQL 覆盖。
重庆展印 Sp_SalSalesCheck 的不同点
文件顶部显示:
- 它从
SysSystemSettings读取'CbxSrcNoCheck'行,决定哪些计费类型进入销售对账报表。这是标准过程可能没有暴露的客户特定开关。 - 它调用全局
Fun_GetLookCustomer(sLoginId, sBrId, sSuId)helper 做权限作用域,与标准过程一致。 - 它接受与标准过程相同的参数列表(
sLoginId/sCustomerId/sBrId/sSuId/bFilter/pageNum/pageSize等),因此框架调用点不变。
未来修订可以与标准 Sp_SalSalesCheck 做并排 diff,精确解释分歧业务规则。当前最重要的是结构事实:过程形状和参数列表与标准一致,主体不同。
配套视图 viw_salsaleschecking_pro.sql 也出于同一原因存在:当覆盖需要标准没有的 join 形状时,工程师编写客户特定视图,并与过程一起应用到该客户 schema。
本切片引入的概念
- 两条定制通道:通过后台编辑元数据(切片 1、2、4)vs. 直接应用到客户 schema 的原始 SQL 覆盖。
- 客户间 schema 分歧:同一过程名在不同客户 DB 中可能表示不同过程,影响维护人员分析运行时行为。
参考项
应新增维护人员页:每客户 SQL 覆盖,记录 script/客户/<customer>/ 约定、手工应用流程、运维影响和审计模式。
待验证项
-
脚本应用是否真的完全手工? 还是存在 Quartz job /
DbToDbController机制?需要读DbToDbServiceImpl.java确认。 -
审计。 写小脚本连接客户 DB,把每个
Sp_*/viw_*主体与标准 diff。意外分歧是运维风险。 -
并排
Sp_SalSalesCheckdiff。 当前只描述结构,未来应纳入实际主体差异,说明重庆展印改变了哪条业务规则以及原因。 - 生命周期。 客户升级、恢复、重建 schema 时,每个覆盖如何重新应用?部署章节需要 runbook。