fix(data): 统一三库 collation(81 张表),跨库 UNION/JOIN 恢复可用
缺陷(P0-6 的后半部分)
----------------------
日期格式统一后,跨库查询仍报:
ERROR 1271 (HY000): Illegal mix of collations for operation 'UNION'
原因是列的 collation 不同:
tushare_data 63 张表 utf8mb4_unicode_ci
akshare_data 18 张表 utf8mb4_unicode_ci(库内自身也不一致)
fin_data_clean 全部 utf8mb4_0900_ai_ci
跨源对账/双源比对因此无法用原生 SQL 完成。
前置条件(本次已满足)
----------------------
collation 变更 MySQL **只能走 COPY 算法(整表重建)**,期间该表禁止写入,
且不可回退 —— 因此先做了完整备份:
~/Library/Application Support/FinDataHub/backups/db-20260918-235703/
tushare_data.sql.gz 1.9G CRC OK, CREATE TABLE 65 条(与本库表数一致)
akshare_data.sql.gz 496M CRC OK, 43 条
fin_data_clean.sql.gz 416M CRC OK, 14 条
备份可用性经 gzip -t 与建表语句计数双重校验。
改动
----
新增 Scripts/bin/migrate_collation.py:
--report 输出待转换清单(按体积升序)
--execute 逐表 ALTER ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci
每表记录前后 collation、行数、残留异类列数;任一异常即 fail-fast
--verify 独立复核 + 端到端跑跨库 UNION/JOIN
选 utf8mb4_0900_ai_ci 为目标:MySQL 8 默认,且 3 个库中 2 个已经是它。
迁移结果(实测)
----------------
转换 81 张表,总耗时 336.9 秒,**0 失败**
每张表行数前后完全一致(如 stock_daily 8,046,947 → 8,046,947)
残留异类列全部为 0
复验:三库 65+43+14 = 122 张表全部符合目标
效果(实测,无需任何显式 COLLATE)
----------------------------------
跨库 UNION : ✓ 返回 2 行
跨库 JOIN 同标的对账 : ✓ 命中 5,547 行(akshare/tushare 同日同标的)
→ 跨源校验通路恢复;此前需在每条 JOIN 上写 COLLATE 才能绕过
回归
----
core 121 / tushare 174 / akshare 183 / Scripts 207 / kuaixun 407 = 1092 passed
银层迁移冒烟(表重建后下游):stock_weekly 11,262 行写入成功,blocked=False,质量分 0.85