我们正在针对同一个数据库运行两个rails应用程序。部署时,我们通常部署到App A,然后部署到App B,在部署期间重新启动所有rails进程。 App A在7台服务器上运行,至少有20个进程连接到数据库。 App B在4台服务器上运行,至少有8个与数据库的连接。
今天,当我们部署App A时,我们在现有表中添加了一列:
change_table :organizations do |t|
t.integer :users_count, default: 0
end
我们预计这会很好:它在现有表上的新列并且它有一个默认值。迁移运行后不久,App A(重启之前)和App B(部署之前)出现了一些错误。
这些错误是:
FATAL ActiveRecord::StatementInvalid error: PG::InFailedSqlTransaction:
ERROR: current transaction is aborted, commands ignored until end of
transaction block
在postgres日志中,我有58个这样的错误:
postgres[12283]: ERROR: cached plan must not change result type
postgres[12283]: STATEMENT: SELECT "organizations".* FROM
"organizations" WHERE "organizations"."id" = $1 LIMIT $2
这会重复多次,并在所有部署完成并重新启动所有进程后消失。
似乎Rails bug #12330和Rails PR 22170在Rails 5.0中解决了这个问题,但是我已经提交了这个错误。
相关软件版本
对Rails bug #12330的一条评论表明我必须添加null默认值的列。另一个建议执行多个部署,一个用于禁用prepare语句,另一个用于执行迁移并重新启用预准备语句。
有没有避免这种情况?当我们重新启动服务器时它会清除,但我觉得我错过了一些东西 - 比如只使用可空列可能会一起避免这些错误。这不会发生在每次部署中,我不知道如何重现它 - 但这不是第一次发生。
答案 0 :(得分:0)
您已更改了表结构,因此更改了准备好的SELECT返回的内容,因为您使用"organizations".*
,并返回所有列。 PostgreSQL显然不支持更新预准备语句,因此您需要创建新会话(重新连接)或使用DEALLOCATE删除该预准备语句。
编辑:您也可以停止使用SELECT *
。