mysql 5.7 升级到 8.0 后 st_* 函数报错,因旧 gis 函数(如 geomfromtext)被彻底移除,且函数语义、srid 要求、wkt 解析严格性、空间索引约束等发生重大变更,需全面适配。

MySQL 5.7 升级到 8.0 后 ST_ 函数报错:Unknown function
MySQL 8.0 彻底移除了旧版 GIS 函数(如 GeomFromText、IsWithin、Distance),全部替换为标准 SQL/MM 的 ST_* 系列函数,但部分旧脚本或 ORM 自动生成的 SQL 仍调用已废弃函数,直接报错 ERROR 1305 (42000): FUNCTION db.GeomFromText does not exist。
关键不是“换名字”,而是函数签名和返回值语义可能变化。比如 Distance(a, b) 在 5.7 返回欧氏距离(无单位),而 ST_Distance(a, b) 在 8.0 默认返回笛卡尔距离,若字段是 POINT 且 SRID=4326,需显式用 ST_DistanceSphere 才得真实米制距离。
- 先确认当前函数是否被弃用:
SELECT routine_name FROM information_schema.routines WHERE routine_schema='mysql' AND routine_name LIKE 'Geom%';—— 8.0 中结果为空 - 批量替换建议用 sed 或正则工具,但注意上下文:
GeomFromText→ST_GeomFromText,AsText→ST_AsText,Contains→ST_Contains - 避免简单全局替换
Distance:它在 5.7 是函数名,在 8.0 是保留字,直接替换为ST_Distance可能引发语法冲突(如字段名也叫distance) - ORM 层(如 MyBatis、Hibernate)若硬编码了旧函数,必须改 mapper XML 或注解,不能只靠数据库兼容层兜底
迁移脚本里含 POLYGON WKT 但报错 ERROR 3617:Invalid GIS data provided
MySQL 8.0 对 WKT(Well-Known Text)解析更严格,尤其对多边形环方向、闭合性、自相交等校验增强。常见错误是旧 dump 文件中 POLYGON((0 0,1 0,1 1,0 1)) 缺少首尾点重合(即没闭合),5.7 宽松接受,8.0 直接拒绝。
这不是字符集或权限问题,而是几何对象构造逻辑变更。即使 ST_IsValid 返回 1,也不代表 WKT 字符串本身符合新 parser 要求。
- 验证单条数据:
SELECT ST_IsValid(ST_GeomFromText('POLYGON((0 0,1 0,1 1,0 1))'));若返回 0,说明未闭合;应改为POLYGON((0 0,1 0,1 1,0 1,0 0)) - 批量修复脚本可用 MySQL 内置函数:对已有字段执行
UPDATE tbl SET geom_col = ST_AsWKT(ST_GeomFromText(ST_AsWKT(geom_col))),强制标准化 - 导入前用
mysqldump --skip-triggers --no-create-info --compact导出,再用sed -E 's/POLYGON\(\(([^)]+)\)\)/POLYGON(((\1,\1)))/g'补闭合(慎用,仅适用于简单矩形) - 注意 SRID:8.0 要求显式声明,如
ST_GeomFromText('POINT(1 1)', 4326),否则默认 SRID=0,后续空间索引可能失效
CREATE SPATIAL INDEX 失败:Unknown column 'geom' in 'spatial index'
MySQL 8.0 要求空间索引只能建在 GEOMETRY 类型列上,且该列不能为 NULL、不能有前缀长度(如 geom(255))、不能是生成列(除非是存储型)。旧表若用 POINT NOT NULL 或 GEOMETRY AS (…),建索引会直接失败。
错误信息里 “Unknown column” 是误导,实际是类型校验不通过,而非列不存在。
- 检查列定义:
SHOW CREATE TABLE tbl_name;确认空间列是GEOMETRY类型,且无AS表达式 - 若列为
POINT,需先转为GEOMETRY:ALTER TABLE tbl MODIFY geom_col GEOMETRY NOT NULL SRID 0; - 若原为虚拟生成列,必须改为存储列:
ALTER TABLE tbl CHANGE geom_col geom_col GEOMETRY STORED NOT NULL; - 建索引时去掉任何长度限制:
CREATE SPATIAL INDEX idx_geom ON tbl(geom_col);—— 不要写geom_col(32)
应用层调用 ST_Distance 返回 NULL,但数据明明存在
这通常不是函数 bug,而是 SRID 不匹配导致的空间参考系无法对齐。例如 MySQL 8.0 默认创建的 POINT 列 SRID=0,而应用传入的 WKT 指定了 SRID=4326,ST_Distance 内部比较时因参考系不同直接返回 NULL。
与字符集乱码类似,这是隐式转换陷阱,日志里不会报错,只静默返回 NULL,极易漏测。
- 查列 SRID:
SELECT ST_SRID(geom_col) FROM tbl LIMIT 1; - 查输入值 SRID:
SELECT ST_SRID(ST_GeomFromText('POINT(116.4 39.9)', 4326)); - 统一 SRID 最稳妥:
ALTER TABLE tbl MODIFY geom_col POINT SRID 4326 NOT NULL;,然后所有插入/更新都带 SRID 参数 - 临时兼容方案:用
ST_Transform转换(需安装 spatial plugin),但性能开销大,仅限验证阶段
ST_Area 结果都可能差几个数量级。务必在迁移前后用 ST_AsBinary 对比原始字节,别只信 ST_AsText 的可读输出。











