Rails执行自定义ALTER TABLE语句时schema_migrations表被清空原因求解
事务异常回滚
Rails迁移默认将整个迁移过程包裹在数据库事务中,你编写的原生SQL执行时如果触发错误(例如roles枚举类型未提前创建、enrollments.role字段存在无法转换为枚举的非法值、数据库操作权限不足等),会触发事务全量回滚。部分旧版本数据库(如PostgreSQL 10及更早版本)存在事务边界处理缺陷,极端情况下会连带回滚迁移流程中写入schema_migrations的操作,甚至触发异常的表数据清空。
测试环境自动schema重置逻辑冲突
Rails测试环境默认开启schema一致性校验,执行rails db:migrate RAILS_ENV=test时,如果项目配置了测试框架自动同步schema的逻辑(如RSpec的use_transactional_fixtures相关配置、minitest的自动schema加载逻辑),可能会隐性触发rails db:schema:load操作:该命令会直接根据schema.rb重建全库,先清空所有表包括schema_migrations,再写入schema.rb中记录的迁移版本。如果schema.rb生成异常、未包含迁移版本记录,执行后就会出现schema_migrations为空的情况。
change方法适配问题
你使用change方法编写原生SQL迁移,Rails的change迁移要求可以自动生成回滚逻辑,但原生execute语句Rails无法自动推断回滚操作。部分版本Rails处理这类不符合change方法规范的迁移时,会中断迁移流程,导致迁移版本没有被正常写入schema_migrations,甚至触发后续的清理逻辑清空已有的版本记录。这类原生SQL迁移建议拆分up和down方法,明确指定迁移和回滚逻辑:
def up execute <<-SQL ALTER TABLE enrollments ALTER role TYPE roles USING role::roles; SQL end def down execute <<-SQL ALTER TABLE enrollments ALTER role TYPE text USING role::text; SQL end
数据库插件/扩展异常
如果数据库开启了DDL审计、数据脱敏类的插件,拦截ALTER TABLE这类DDL操作时出现逻辑异常,可能会破坏Rails迁移的正常执行流程,误操作清空schema_migrations表的数据。
内容的提问来源于stack exchange,提问作者HJW

