2012-09-25 4 views
4

전자 메일 목록을 가져 와서 postgres 데이터베이스에 저장하는 가져 오기 기능이 있습니다. 여기에 tableless의 수입 클래스 내에서 코드 중 일부이다이 모두 하나 개의 동작으로 이루어집니다PG :: ERROR : 다른 명령이 이미 실행 중입니다

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

:

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 

오전 데 문제는 내가 업로드하려고 할 때 예외를 얻을 수 있다는 것입니다 , 내가하고있는 유일한 다른 쿼리는 사용자 유효성 검사이고 중복 된 가져 오기를 방지하는 DB 뮤텍스가 있습니다. 이 쿼리는 0.13.2에서 0.14.1로 내 pg gem을 업데이트하는 것을 포함한 최근의 푸시 (다른 "관련없는"코드와 함께)까지 제대로 작동했습니다.

오류는 처음에는 준비 서버에서 시작되었지만 로컬로 재현 할 수 있었으며 아이디어가 없습니다.

내 질문에 더 분명하게 대답해야한다면 알려주십시오.) (

감사

답변

9

내 자신의 대답을 발견하고 "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) 
+3

도있다 [더 완벽한 예 (https://bitbucket.org : 나는 또한 성공적인 수입의 경우 흐름을 방해하지 않고, 다시 풀에 연결을 해제 끝에이 추가 /gp/typ/sample/copyfrom.rb)'pg' 라이브러리의 샘플 디렉토리에서 원시 PG 연결을 사용하여이를 수행하는 방법을 설명합니다. 오류 처리를 추가하고 #get_result에서 얻은 Result 객체를 어떻게 사용하는지 보여줍니다. –

+0

다른 메모를 추가하기 만하면 기존 연결을 사용하는 경우 checkin (conn) 할 필요가 없습니다. conn = ActiveRecord :: Base.connection –

+0

감사합니다. 내게 정말 도움이됩니다. –

관련 문제