# 废弃/备份嫌疑表 —— 逐张确认 > 本文件由 `sql/tools/audit_junk_tables.py` 生成,**不要手改**(重跑会覆盖)。 > 判据与结论口径见该脚本文件头。**名字只是嫌疑**,证据是精确行数 + 代码引用 + 建表时间。 ## 自检 - 分表族(运行期拼后缀的活表)已排除 **228 张**;独立用 MySQL `LIKE` 复查得 **228 张**——✅ 一致 - `tp_p_eqp_inout_record` **115 张**(tp_p_eqp_inout_record201709 ~ tp_p_eqp_inout_record202703) - `tp_p_eqp_log` **113 张**(tp_p_eqp_log201711 ~ tp_p_eqp_log202703) - 族清单完整性:用 `sharded_in_code()`(**代码里有没有 `"前缀"` 字面量**)双向反查——✅ 登记的都真在拼、在拼的都登记了 - 名字像族、**但代码没拼**(人工快照,不是族,照常走嫌疑判据): - `park_free_berth` 2 张:`park_free_berth_20180915`、`park_free_berth_20181027` - `parking_running_statistic` 2 张:`parking_running_statistic2023`、`parking_running_statistic2025` - `tp_p_eqp` 4 张:`tp_p_eqp_20180915`、`tp_p_eqp_20181121`、`tp_p_eqp_20181218`、`tp_p_eqp_20190114` - 分表族前缀下**未按族排除**的成员(有意放行,照常走嫌疑判据): - `zt_order_n.pay_order` - `zt_order_n.pay_order_barcode` - `zt_order_n.pay_order_chifeng_20181214_bak` - `zt_order_n.pay_order_success` - `zt_order_n.pay_order_success_1202` - `zt_park.tp_p_eqp_inout_record` - `zt_park.tp_p_eqp_inout_record_temp` - `zt_park.tp_p_eqp_log` - 代码引用口径:命中分两级——`表位置`(`FROM/JOIN/INTO/UPDATE/TABLE/EXISTS` 之后,或 Java 里的**带引号字面量**)记为硬证据;其余词边界命中记为**疑似**,因为 `FROM duty_roster_base_temp temp` 里的 `temp` 是**别名不是表名**,实测就靠这个把 7 行的 `zt_park.temp` 报成了「有引用」。两级都会贴出命中行原文,一眼可判 - 扫描根:`/Users/wangbiao/IdeaProjects/parking/parking-cloud/sql/tools/../..` > ⚠️ 自检项分散在生成过程的各处(代码引用要扫完仓才知道、`DO_NOT_MIGRATE` 要复核完才敢确认),所以**告警统一在文末「自检告警」一节列出**——别只看这上面几行。(踩过:告警块原先写在这一节里,`DO_NOT_MIGRATE` 那批复核是在它**之后**才追加进 `bad` 的,于是退出码 2、报告里一个字都没提。) ## 总计 61 张嫌疑表 | 库 | 张数 | |---|---:| | `zt_bill` | 5 | | `zt_order` | 8 | | `zt_order_n` | 13 | | `zt_park` | 27 | | `zt_sys` | 8 | ## `zt_bill`(5 张) | 表 | 命中判据 | 精确行数 | 大小 | 建表时间 | 代码引用 | 建议处置 | |---|---|---:|---:|---|---|---| | `tb_r_whitelist_park_rel_del_190104` | _<6位年月> 后缀 | 219 | 48.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `td_cl_park_rule_collect_rel_copy1` | _copy 副本 | 22 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `t_vip_area_card_cust_info_bak` | _bak 备份 | 25,023 | 10.4 MB | 2025-06-20 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `t_vip_area_card_cust_info_rel_bak` | _bak 备份 | 5,555,582 | 494.0 MB | 2025-06-20 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `t_vip_card_cust_info_bak` | _bak 备份 | 340 | 112.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | ## `zt_order`(8 张) | 表 | 命中判据 | 精确行数 | 大小 | 建表时间 | 代码引用 | 建议处置 | |---|---|---:|---:|---|---|---| | `td_b_bills_days_bak` | _bak 备份 | 2,705 | 448.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `td_b_pay_blncac_diff_copy` | _copy 副本 | 0 | 16.0 KB | 2022-07-27 | — | ⬛ 已拍板不搬(空表) —— _copy 副本,0 行(zt_order) | | `td_b_pay_order_bak_20170927` | _bak 备份 | 89,398 | 13.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `td_b_temp_parklot` | 名含 temp | 3,372 | 352.0 KB | 2022-07-27 | 表位置 **2** / 疑似 0 | 🔴 有代码引用 —— **不能按名字处置**——先看引用是活代码还是死代码 | | `td_c_acct_payout_copy` | _copy 副本 | 305,717 | 62.6 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `td_c_cust_invoice_sale_copy1` | _copy 副本 | 2 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `td_c_recharge_card_1115` | _<4位数字> 后缀 | 530 | 128.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `td_p_parking_share_order_temp` | 名含 temp | 0 | 16.0 KB | 2022-07-27 | 表位置 **4** / 疑似 0 | 🔴 有代码引用 —— **不能按名字处置**——先看引用是活代码还是死代码 | ## `zt_order_n`(13 张) | 表 | 命中判据 | 精确行数 | 大小 | 建表时间 | 代码引用 | 建议处置 | |---|---|---:|---:|---|---|---| | `charger_income_statistic_day_copy` | _copy 副本 | 76,015 | 25.6 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `income_finance_bill_0506` | _<4位数字> 后缀 | 30 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `income_finance_bill_bak_xicheng` | _bak 备份 | 1,754 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `income_statistic_park_month_0125` | _<4位数字> 后缀 | 4,368 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `income_statistic_vip_card_month_0125` | _<4位数字> 后缀 | 3,953 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `income_temp` | 名含 temp | 353 | 64.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `mytest` | 名含 test | 685 | 80.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `order_park_chifeng_20181214_bak` | _bak 备份 | 154,309 | 106.7 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `pay_order_chifeng_20181214_bak` | _bak 备份 | 127,357 | 27.6 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `pay_order_success_1202` | _<4位数字> 后缀 | 2,478,107 | 1.1 GB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `td_b_pay_blncac_result_bak` | _bak 备份 | 0 | 16.0 KB | 2022-07-27 | — | ⬛ 已拍板不搬(空表) —— _bak 备份,0 行(zt_order_n) | | `td_p_parking_share_order_temp` | 名含 temp | 0 | 16.0 KB | 2022-07-27 | 表位置 **4** / 疑似 0 | 🔴 有代码引用 —— **不能按名字处置**——先看引用是活代码还是死代码 | | `test_check` | 名含 test | 3 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | ## `zt_park`(27 张) | 表 | 命中判据 | 精确行数 | 大小 | 建表时间 | 代码引用 | 建议处置 | |---|---|---:|---:|---|---|---| | `del20181116td_g_first_guide_info_config` | del 前缀带日期 | 0 | 16.0 KB | 2022-07-27 | — | ⬛ 已拍板不搬(空表) —— del<日期> 残留,0 行(zt_park) | | `del20181116td_g_guide_park_berths` | del 前缀带日期 | 0 | 16.0 KB | 2022-07-27 | — | ⬛ 已拍板不搬(空表) —— del<日期> 残留,0 行(zt_park) | | `duty_roster_base_temp` | 名含 temp | 1,250 | 304.0 KB | 2022-07-27 | 表位置 **2** / 疑似 0 | 🔴 有代码引用 —— **不能按名字处置**——先看引用是活代码还是死代码 | | `eqp_virtual_park_record_chifeng_20190622` | _<8位日期> 后缀 | 1,515,176 | 235.9 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `eqp_virtual_park_record_temp` | 名含 temp | 1,515,176 | 200.8 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `eqp_virtual_park_record_temp_0630` | _<4位数字> 后缀 | 8,873 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `income_temp` | 名含 temp | 353 | 64.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `parking_lot_20180915` | _<8位日期> 后缀 | 1,413 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `parking_lot_berth_temp_info` | 名含 temp | 57 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `parking_lot_chifeng_20181214_bak` | _bak 备份 | 81 | 128.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `parking_lot_geo_20180915` | _<8位日期> 后缀 | 2,933 | 480.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `parking_running_statistic2023` | 裸<数字>后缀 | 超限未数(估 385,739,913) | 81.0 GB | 2024-05-22 | — | ⬛ 已拍板不搬(备份) —— 滚动快照(建表 2024-05-22,3.86 亿行 / 约 83 GB),代码零引用;**2026-10-10 业务方拍板「备份表,无需理会」** | | `parking_running_statistic2025` | 裸<数字>后缀 | 超限未数(估 241,479,210) | 49.3 GB | 2026-04-17 | — | ⬛ 已拍板不搬(备份) —— 滚动快照(建表 2026-04-17,2.41 亿行 / 约 50 GB),代码零引用;**2026-10-10 业务方拍板「备份表,无需理会」** | | `parking_running_statistic_chifeng_2019021` | 裸<数字>后缀 | 超限未数(估 19,472,213) | 3.5 GB | 2022-07-27 | — | 🟡 无引用但行数未知 —— 行数超限未数,定处置前先取精确 COUNT(*) | | `park_free_berth_20180915` | _<8位日期> 后缀 | 1,455 | 176.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `park_free_berth_20181027` | _<8位日期> 后缀 | 1,538 | 192.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `park_free_berth_temp` | 名含 temp | 1,538 | 192.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `td_g_guide_park_rel_copy1` | _copy 副本 | 238 | 64.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `temp` | 名含 temp | 7 | 16.0 KB | 2022-07-27 | 表位置 **0** / 疑似 6 | 🟠 疑似引用(非表位置) —— 6 个文件命中,但**没有一处出现在表位置**(`FROM/JOIN/…` 之后或 Java 字面量),多半是 SQL 别名或变量——人工扫一眼明细即可判 | | `tp_p_berths_20180915` | _<8位日期> 后缀 | 7,446 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `tp_p_berths_chifeng_2018214_bak` | _bak 备份 | 5,840 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `tp_p_eqp_20180915` | _<8位日期> 后缀 | 3,922 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `tp_p_eqp_20181121` | _<8位日期> 后缀 | 4,177 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `tp_p_eqp_20181218` | _<8位日期> 后缀 | 5,184 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `tp_p_eqp_20190114` | _<8位日期> 后缀 | 4,342 | 1.5 MB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `tp_p_eqp_inout_record_temp` | 名含 temp | 843,979 | 193.8 MB | 2022-07-27 | 表位置 **1** / 疑似 0 | 🔴 有代码引用 —— **不能按名字处置**——先看引用是活代码还是死代码 | | `tp_p_pda_20180905` | _<8位日期> 后缀 | 367 | 80.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | ## `zt_sys`(8 张) | 表 | 命中判据 | 精确行数 | 大小 | 建表时间 | 代码引用 | 建议处置 | |---|---|---:|---:|---|---|---| | `del_sys_code_bak` | _bak 备份 | 2 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `del_sys_code_def_bak` | _bak 备份 | 112 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `sys_export_temp_file` | 名含 temp | 0 | 16.0 KB | 2022-07-27 | 表位置 **1** / 疑似 0 | 🔴 有代码引用 —— **不能按名字处置**——先看引用是活代码还是死代码 | | `sys_op_advice_bak` | _bak 备份 | 1,416,452 | 200.8 MB | 2026-02-25 | — | ⬛ 已拍板不搬(备份) —— 滚动前的旧表副本(建表 2026-02-25,109 万行 / 200 MB),代码零引用;**2026-10-10 业务方拍板「备份表,无需理会」** | | `sys_org_copy` | _copy 副本 | 9 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `sys_org_copy2` | _copy 副本 | 90 | 16.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `sys_res_bak` | _bak 备份 | 140 | 48.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | | `sys_res_jobfunc_bak` | _bak 备份 | 2,651 | 176.0 KB | 2022-07-27 | — | 🟡 有数据但无引用 —— 导出留痕后丢,或随迁(默认`先全搬`) | ## 🔴/🟠 有命中的:明细(要逐条判断是活代码还是死代码) > `表位置` = 硬证据;`疑似` = 命中词不在表位置,**看下面贴的原文**:`FROM tmp_x temp` 这种是别名,不算引用。 ### `zt_order`.`td_b_temp_parklot` **表位置**(2) - `parking-module-pay/src/main/resources/mybatis/mapper/TdBTempParklotMapper.xml`:14 — `insert into td_b_temp_parkLot (pl_no, pl_name, block_no,` - `parking-module-pay/src/main/resources/mybatis/smapper/TdBTempParklotSMapper.xml`:15 — `INSERT INTO td_b_temp_parkLot(pl_no,pl_name,block_no,block_name,berth_range_no,berth_range_name,berths) VALUES` ### `zt_order`.`td_p_parking_share_order_temp` **表位置**(4) - `parking-module-order/src/main/resources/mybatis/mapper/smapper/TdBSettlementShareRecordSMapper.xml`:234 — `FROM td_p_parking_share_order_temp x` - `parking-module-order/src/main/resources/mybatis/mapper/smapper/TdPParkingShareOrderTempSMapper.xml`:40 — `TRUNCATE TABLE td_p_parking_share_order_temp;` - `parking-module-pay/src/main/resources/mybatis/mapper/TdPParkingShareOrderTempMapper.xml`:41 — `from td_p_parking_share_order_temp` - `parking-module-pay/src/main/resources/mybatis/smapper/TdPParkingShareOrderTempSMapper.xml`:40 — `TRUNCATE TABLE td_p_parking_share_order_temp;` ### `zt_order_n`.`td_p_parking_share_order_temp` **表位置**(4) - `parking-module-order/src/main/resources/mybatis/mapper/smapper/TdBSettlementShareRecordSMapper.xml`:234 — `FROM td_p_parking_share_order_temp x` - `parking-module-order/src/main/resources/mybatis/mapper/smapper/TdPParkingShareOrderTempSMapper.xml`:40 — `TRUNCATE TABLE td_p_parking_share_order_temp;` - `parking-module-pay/src/main/resources/mybatis/mapper/TdPParkingShareOrderTempMapper.xml`:41 — `from td_p_parking_share_order_temp` - `parking-module-pay/src/main/resources/mybatis/smapper/TdPParkingShareOrderTempSMapper.xml`:40 — `TRUNCATE TABLE td_p_parking_share_order_temp;` ### `zt_park`.`duty_roster_base_temp` **表位置**(2) - `parking-module-park/src/main/resources/mybatis/mapper/DutyRosterBaseTempMapper.xml`:98 — `from duty_roster_base_temp` - `parking-module-park/src/main/resources/mybatis/smapper/DutyRosterBaseSMapper.xml`:119 — `FROM duty_roster_base_temp temp` ### `zt_park`.`temp` **疑似**(6) - `parking-module-order/src/main/resources/mybatis/mapper/smapper/TdPParkingShareOrderTempSMapper.xml`:56 — `` - `parking-module-park/src/main/resources/mybatis/smapper/ChargerIncomeDiffSMapper.xml`:175 — `sum(temp.eqpNum) eqpNum,` - `parking-module-park/src/main/resources/mybatis/smapper/DutyRosterBaseSMapper.xml`:119 — `FROM duty_roster_base_temp temp` - `parking-module-park/src/main/resources/mybatis/smapper/EqpVirtualParkRecordStatisticSMapper.xml`:97 — `temp.pl_no pl_no,` - `parking-module-pay/src/main/resources/mybatis/smapper/TdBTempParklotSMapper.xml`:16 — `` - `parking-module-pay/src/main/resources/mybatis/smapper/TdPParkingShareOrderTempSMapper.xml`:56 — `` ### `zt_park`.`tp_p_eqp_inout_record_temp` **表位置**(1) - `parking-module-park/src/main/resources/mybatis/mapper/TpPEqpInoutRecordTempMapper.xml`:99 — `from tp_p_eqp_inout_record_temp` ### `zt_sys`.`sys_export_temp_file` **表位置**(1) - `parking-module-system/src/main/resources/mybatis/mapper/SysExportTempFileMapper.xml`:23 — `from sys_export_temp_file` ## 已拍板:不搬进新库的表(7 张 = 空表 4 + 有数据的备份 3) > 单一事实来源是 `audit_junk_tables.py` 的 `DO_NOT_MIGRATE`,迁移脚本(`gen_migration_sql.py`)直接 import 它并写进 `sql/migration/exclude_tables.txt`(`mysqldump --ignore-table`)、`99_verify.sql` §1 的 `NOT IN`、`98_count_reconcile.sql` 的排除集。 > > **两层的守卫强度不一样**(见脚本文件头): > `空表` 靠**数据自证**——仍存在、仍 0 行、仍无表位置引用,逐条复核; > `备份` 是**外部拍板**,本工具只能守它的前提——仍存在、仍无表位置引用。**"这是不是你需要的备份"没有任何查询能回答**。 > > ⚠️ 所以 `备份` 那几张**是有数据的**:不搬 = 那批历史行只留在老库(老库只读保留、未被销毁,需要时可单独导出),但**新库里确实没有**。理由串里的"谁、什么时候、凭什么"是这件事**唯一**的留痕处。 | 表 | 层级 | 理由 | |---|---|---| | `zt_order.td_b_pay_blncac_diff_copy` | 空表 | _copy 副本,0 行(zt_order) | | `zt_order_n.td_b_pay_blncac_result_bak` | 空表 | _bak 备份,0 行(zt_order_n) | | `zt_park.del20181116td_g_first_guide_info_config` | 空表 | del<日期> 残留,0 行(zt_park) | | `zt_park.del20181116td_g_guide_park_berths` | 空表 | del<日期> 残留,0 行(zt_park) | | `zt_park.parking_running_statistic2023` | 备份 | 滚动快照(建表 2024-05-22,3.86 亿行 / 约 83 GB),代码零引用;**2026-10-10 业务方拍板「备份表,无需理会」** | | `zt_park.parking_running_statistic2025` | 备份 | 滚动快照(建表 2026-04-17,2.41 亿行 / 约 50 GB),代码零引用;**2026-10-10 业务方拍板「备份表,无需理会」** | | `zt_sys.sys_op_advice_bak` | 备份 | 滚动前的旧表副本(建表 2026-02-25,109 万行 / 200 MB),代码零引用;**2026-10-10 业务方拍板「备份表,无需理会」** | ## 结论分布 | 结论 | 张数 | |---|---:| | ⬛ 已拍板不搬(备份) | 3 | | ⬛ 已拍板不搬(空表) | 4 | | 🔴 有代码引用 | 6 | | 🟠 疑似引用(非表位置) | 1 | | 🟡 无引用但行数未知 | 1 | | 🟡 有数据但无引用 | 46 | > 处置决定拍板后,写回 [`../legacy-db-actual.md`](../legacy-db-actual.md) §8,并在 `check_subset.py` / 排除清单里落地——**别只改这份报告**(它是生成物)。 ## 自检告警 ✅ 全部自检通过(退出码 0)。 即:分表族两套实现一致、族清单被代码判据双向确认、`DO_NOT_MIGRATE` 逐条的**前提**仍成立——两层共有的前提是**代码里没人读它**,`空表` 层另有"仍是 0 行"。 ⚠️ 注意这条自检的**边界**:它只能证明"不就已知前提报警",证明不了"不搬这个决定本身是对的"——`备份` 层的理由("这是备份,不用管")是业务判断,报告里的任何一行都不是它的证据。