【问题标题】:PG::ERROR: another command is already in progressPG::ERROR: 另一个命令已经在进行中
【发布时间】:2012-09-17 13:00:31
【问题描述】:

我有一个导入器,它获取电子邮件列表并将它们保存到 postgres 数据库中。这是无表导入器类中的一段代码:

query_temporary_table = "CREATE TEMPORARY TABLE subscriber_imports (email CHARACTER VARYING(255)) ON COMMIT DROP;"
query_copy            = "COPY subscriber_imports(email) FROM STDIN WITH CSV;"
query_delete          = "DELETE FROM subscriber_imports WHERE email IN (SELECT email FROM subscribers WHERE suppressed_at IS NOT NULL OR list_id = #{list.id}) RETURNING email;"
query_insert          = "INSERT INTO subscribers(email, list_id, created_at, updated_at) SELECT email, #{list.id}, NOW(), NOW() FROM subscriber_imports RETURNING id;"

conn = ActiveRecord::Base.connection_pool.checkout
conn.transaction do
  raw = conn.raw_connection

  raw.exec(query_temporary_table)
  raw.exec(query_copy)
  CSV.read(csv.path, headers: true).each do |row|
    raw.put_copy_data row['email']+"\n" unless row.nil?
  end
  raw.put_copy_end
  while res = raw.get_result do; end # very important to do this after a copy

  result_delete = raw.exec(query_delete)
  result_insert = raw.exec(query_insert)

  ActiveRecord::Base.connection_pool.checkin(conn)
  {
    deleted:  result_delete.count,
    inserted: result_insert.count,
    updated:  0
  }
end

我遇到的问题是,当我尝试上传时出现异常:

PG::ERROR: another command is already in progress: ROLLBACK

这一切都在一个动作中完成,我要做的唯一其他查询是用户验证,并且我有一个数据库互斥锁来防止重叠导入。在我最近一次推送之前,此查询运行良好,其中包括将我的 pg gem 从 0.13.2 更新到 0.14.1(以及其他“不相关”代码)。

错误最初是在我们的暂存服务器上开始的,但后来我能够在本地重现它,但我没有想法。

如果我需要更清楚我的问题,请告诉我。

谢谢

【问题讨论】:

    标签: ruby postgresql activerecord import pg


    【解决方案1】:

    找到我自己的答案,如果有人在使用“COPY”导入大量数据时发现同样的问题,这可能会很有用

    在 CSV.read() 块中引发了一个异常,我确实捕获了它,但我没有正确结束该过程。

      begin
        CSV.read(csv.path, headers: true).each do |row|
          raw.put_copy_data row['email']+"\n" unless row.nil?
        end
      ensure
        raw.put_copy_end
        while res = raw.get_result do; end # very important to do this after a copy
      end
    

    此块确保 COPY 命令完成。我还在最后添加了这个以将连接释放回池中,而不会在导入成功的情况下中断流程:

    rescue
      ActiveRecord::Base.connection_pool.checkin(conn)
    

    【讨论】:

    • pg 库的示例目录中还有a more complete example 说明如何使用原始PG 连接执行此操作。它添加了错误处理并显示您可能希望如何使用从 #get_result 获得的 Result 对象。
    • 只是添加一个注释,如果您使用现有连接,则无需签入(conn):conn = ActiveRecord::Base.connection
    • 谢谢,对我很有帮助:)
    猜你喜欢
    • 1970-01-01
    • 2018-06-29
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 2020-07-18
    • 2021-12-01
    • 2011-09-25
    • 2016-01-04
    相关资源
    最近更新 更多