Sequel迁移单表失败问题求助
这个错误本质是PostgreSQL事务因为某个前置错误被中断了,后续所有命令都被拒绝执行——但你看到的错误只是“事务已失败”的提示,真正的问题藏在这条错误之前的数据库日志里。结合你的表结构代码,我整理了几个大概率的排查方向和修复方案:
1. 修正CHECK约束的写法
你手动构造Sequel::SQL::BooleanExpression来定义CHECK约束的方式容易出错,Sequel本身提供了更简洁且不易出错的块式语法,能确保生成的SQL完全符合PostgreSQL规范。
修复后的表创建代码
create_table(:utilization_disks, :ignore_index_errors=>true) do primary_key :id, :type=>:Bignum String :ip, :size=>64, :null=>false String :device, :size=>16 Integer :read_ops Integer :write_ops Integer :read_kbytes Integer :write_kbytes DateTime :tstamp # 改用Sequel推荐的块式语法定义CHECK约束 check { read_ops >= 0 } check { write_ops >= 0 } check { read_kbytes >= 0 } check { write_kbytes >= 0 } # 移除冗余的主键索引:primary_key会自动创建唯一索引,手动添加会重复 index [:ip], :name=>:index_utilization_disks_ip index [:tstamp], :name=>:index_utilization_disks_tstamp end
2. 查看PostgreSQL原始错误日志
PG::InFailedSqlTransaction只是事务失败的“结果”,不是“原因”。你需要查看PostgreSQL服务器的日志文件(通常在/var/log/postgresql/目录下,具体路径取决于部署方式),找到这条错误之前的具体报错信息——比如可能是约束语法错误、索引名称重复,或者字段类型不兼容等。
3. 验证Sequel生成的SQL语句
如果还是找不到问题,可以在迁移文件开头添加日志输出,查看Sequel实际发送给数据库的SQL:
# 在迁移文件顶部添加,输出所有执行的SQL DB.loggers << Logger.new($stdout) # 后续是你的create_table代码...
把生成的CREATE TABLE语句复制到psql客户端直接执行,PostgreSQL会返回精确的错误原因,这是定位问题最快的方式。
4. 排除冗余索引的干扰
虽然你加了:ignore_index_errors=>true,但手动添加的主键索引(index [:id], :name=>:id, :unique=>true)完全冗余——Sequel的primary_key方法会自动创建一个唯一的主键索引。某些PostgreSQL版本对重复创建同名/同定义索引的处理可能会触发事务中断,移除这条冗余索引能避免潜在冲突。
内容的提问来源于stack exchange,提问作者Mlok

