使用Rails Active Record更新MEDIUMTEXT字段触发Mysql2长度超限错误排查
错误触发原因
- Rails Schema 缓存类型映射错误
如果该字段最初创建时为TEXT类型,后续通过迁移修改为MEDIUMTEXT后没有清空Rails Schema缓存,Active Record会始终将该字段识别为最大长度65535字节的TEXT类型,在写入前自动触发提前长度校验,超出限制就会抛出错误。新增记录时部分配置场景下会跳过该层提前校验,直接将SQL发送到数据库执行,而数据库本身字段为MEDIUMTEXT支持更长内容,因此不会报错。你将字段值设为空字符串时内容长度远低于TEXT上限,因此校验可以通过,更新不会报错。 - 旧版本
mysql2gem类型识别bug
0.5.3版本以下的mysql2gem存在MEDIUMTEXT类型映射错误问题,会统一将所有TEXT子类识别为默认的TEXT类型,导致Active Record应用错误的长度限制。 - Active Record脏属性校验逻辑差异
更新操作时Active Record只会对发生变更的脏属性执行提前校验,而新增操作时部分配置下会跳过该层校验,直接交由数据库处理,因此相同内容新增可以写入、更新会被拦截。
解决方案
- 清空Schema缓存
执行对应环境的缓存清理命令:开发环境执行rails tmp:cache:clear,生产环境执行rails db:schema:cache:clear后重启服务,让Active Record重新加载最新的字段类型配置。 - 升级
mysql2gem到稳定版
在Gemfile中修改mysql2依赖版本为gem 'mysql2', '>= 0.5.3',执行bundle update mysql2后重启服务即可修复类型映射错误问题。 - 模型中显式指定字段类型
如果上述方案无法生效,可以在对应模型中手动声明字段类型,覆盖默认的映射逻辑:
class 你的模型名 < ApplicationRecord attribute :object, :mediumtext end
- (不推荐)关闭提前校验
如果需要临时解决,可以在config/database.yml对应数据库配置项下添加strict: false,关闭Active Record的提前长度校验,直接交由数据库处理写入逻辑。
内容的提问来源于stack exchange,提问作者Joel Cahalan
相关产品推荐
相关产品推荐

