| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- -- 1.0.520.verify.sql — 每条 SELECT 都必须返回真值(0 或 NULL 即判失败并中断启动)
- -- ── 1 · 新键到位:四列、列序正确 ─────────────────────────────────────────────────────
- -- 与 1.0.517.verify 同法,用 GROUP_CONCAT 比列序列字符串,不对 information_schema 施加 COLLATE
- -- (部分 MySQL 版本上它是 utf8mb3,强加 utf8mb4_bin 会让 verify 脚本自己把启动打挂)。
- SELECT IFNULL((SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) FROM information_schema.STATISTICS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'mdp_stg_so'
- AND INDEX_NAME = 'uk_source_key'), '')
- = 'tenant_id,source_system,source_table,source_biz_key';
- -- tenant_id 必须是第 1 列:贴源的绝大多数读法都以 tenant_id 打头,
- -- 放在末列虽然唯一性等价,却让这个索引无法为租户内检索提供前缀。
- SELECT (SELECT SEQ_IN_INDEX FROM information_schema.STATISTICS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'mdp_stg_so'
- AND INDEX_NAME = 'uk_source_key' AND COLUMN_NAME = 'tenant_id') = 1;
- -- 必须仍然是 UNIQUE:若退化成普通索引,upsert 的 ON DUPLICATE KEY 会整个失效,
- -- 贴源从「覆盖」变成「无限追加」,比原缺陷更糟。
- SELECT (SELECT COUNT(*) FROM information_schema.STATISTICS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'mdp_stg_so'
- AND INDEX_NAME = 'uk_source_key' AND NON_UNIQUE = 0) = 4;
- -- ── 2 · 跨租户覆盖路径已关闭 ─────────────────────────────────────────────────────────
- -- 本条是本批的核心断言:mdp_stg_so 上不得再存在任何「不含 tenant_id 的唯一约束」。
- -- 只钉 uk_source_key 是不够的 —— 任何一个漏了 tenant_id 的唯一索引都会重新变成
- -- ON DUPLICATE KEY 的冲突判据,把跨租户覆盖路径再打开一次。
- SELECT (SELECT COUNT(*) FROM (
- SELECT INDEX_NAME FROM information_schema.STATISTICS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'mdp_stg_so'
- AND NON_UNIQUE = 0 AND INDEX_NAME <> 'PRIMARY'
- GROUP BY INDEX_NAME
- HAVING SUM(COLUMN_NAME = 'tenant_id') = 0) x) = 0;
- -- 存量在新键下无冲突(唯一索引在位时必然成立,作为落库后的兜底自检)。
- SELECT (SELECT COUNT(*) FROM (
- SELECT 1 FROM `mdp_stg_so`
- GROUP BY `tenant_id`,`source_system`,`source_table`,`source_biz_key`
- HAVING COUNT(*) > 1) x) = 0;
- -- ── 3 · 贴源层与标准层口径已对齐 ─────────────────────────────────────────────────────
- -- 本批的意义就是消除两层不一致,故把 mdp_std_so 的键一起钉住,防止有人反向「对齐」到窄键。
- SELECT IFNULL((SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) FROM information_schema.STATISTICS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'mdp_std_so'
- AND INDEX_NAME = 'uk_source_key' AND NON_UNIQUE = 0), '')
- = 'tenant_id,source_system,source_table,source_biz_key';
- -- ── 4 · 1.0.356 建立的作用域 CHECK 未被本批动过 ──────────────────────────────────────
- -- 该 CHECK 保证 tenant_id 非空且不是平台/默认租户,是「键里有 tenant_id」能真正隔离的前提:
- -- 若 tenant_id 可为 NULL,MySQL 唯一索引会把多个 NULL 视为互不相同,隔离与去重会同时失效。
- SELECT (SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
- WHERE CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = 'mdp_stg_so'
- AND CONSTRAINT_NAME = 'ck_mdp_stg_so_valid_scope') = 1;
- -- 存量 tenant_id 必须真的可用:无 NULL、无 0/1/默认租户。
- -- 键里有 tenant_id 但该列是空的,隔离等于没做。
- SELECT (SELECT COUNT(*) FROM `mdp_stg_so`
- WHERE `tenant_id` IS NULL OR `tenant_id` IN (0, 1, 1300000000001)) = 0;
|