首页 > 解决方案 > PG::ConnectionBad: PQsocket() 无法获取套接字描述符:删除记录时的 ROLLBACK

问题描述

跑步:

Price.find(208999).delete

rails 控制台中,导致错误消息:

SQL (0.0ms)  DELETE FROM "prices" WHERE "prices"."id" = $1  [["id", 208999]]
ActiveRecord::StatementInvalid: PG::ConnectionBad: PQsocket() can't get 
socket descriptor: DELETE FROM "prices" WHERE "prices"."id" = $1'

随后重试同一命令会导致:

SQL (4.0ms)  DELETE FROM "prices" WHERE "prices"."id" = $1  [["id", 208999]]
ActiveRecord::StatementInvalid: PG::ConnectionBad: PQconsumeInput() server 
closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
: DELETE FROM "prices" WHERE "prices"."id" = $1

此时我无法运行任何查询命令而不会遇到此问题。在我运行删除之前,我可以删除另一个表上的另一个 SQL。

我已经尝试了与此错误相关的堆栈溢出的所有其他链接:

我没有设置任何 spec/rspec rake 任务,但是我尝试过rails tmp:clear哪些状态,“# Clear cache and socket files from ...”

我检查了是否有将此记录与另一个表关联,但是我的搜索没有返回任何内容。

标签: sqlruby-on-railspostgresqlruby-on-rails-5

解决方案


经过几个小时的搜索...

问题是在我的 price.rb 模型文件中,我声明了以下关系:

class Price < ApplicationRecord
    belongs_to :card

    has_and_belongs_to_many :collections

    has_many :types

    class << self # Class methods
    end
end

我删除了price.types关联记录,但是我没有采取其他方式并删除card.prices关联记录。

所以我在哪里运行的命令:

price = Price.find(208999)

card = price.card

#delete price_card association record
card.prices.delete(price)

#now i'll be able to delete the price record
price.delete

确实需要为此提供更好的错误消息,因为我一直在修改我的 database.yml 文件并重置我的套接字,因为这就是错误消息让您相信的内容。

希望这将在其他人开始搞乱数据库配置之前对其有所帮助。


编辑 2

刚刚再次遇到这个问题,我更新到最新版本的 PostgreSQL,即 12.4,因为我阅读了dba stackexchange 答案,这是在我正在运行的 PostgreSQL 11 中发出 DELETE sql 命令时的常见问题。

它并没有解决问题。

下载并仔细查看 pgAdmin4 生成的日志文件后,我发现了对关系键的引用,因此我创建了一个小脚本来循环所有记录,并将任何外键值设置为,nil因此在删除时,它没有抛出任何令人讨厌的错误。

Product.all.each do |product|
  product.update(cardset_id:nil,language_id:nil)
  product.delete
end

编辑 3

所以我终于弄清楚了我的 PostgreSQL 数据库发疯的真正原因..

我有一个名为 Cards 的表,其中有一个unique: true设置了选项的 slug 字段。

在我的 Card 模型中,我有一个函数

extend FriendlyId
friendly_id (:slug_id), use: :slugged

def slug_id
    [
        [:name, :cardset_id],
    ]
end

通过名称和 cardset_id 的混合创建了一个 slug,但是如果我想要同一记录的不同副本,则出于某种原因创建相同的 slug id。

当 PostgreSQL 去获取这条记录时,它会中断,因为数据没有意义,而且它本来就不应该存在。

所以我的 slug 函数没有按预期运行有问题。

在删除每条记录之前,我只是将 slug 设置为随机值,然后将其删除。


推荐阅读