수색…


비고

트랜잭션은 SQL 문이 모두 하나의 기본 동작으로 성공할 수있는 경우에만 영구적 인 보호 블록입니다. 고전적인 예는 인출이 성공한 경우에만 입금 할 수있는 두 개의 계좌 간의 이체 및 그 반대의 경우입니다. 트랜잭션은 데이터베이스의 무결성을 강화하고 프로그램 오류 또는 데이터베이스 고장으로부터 데이터를 보호합니다. 따라서 기본적으로 트랜잭션 블록을 사용해야합니다. 여러 개의 명령문을 함께 실행해야하거나 전혀 실행하지 않아야합니다.

기본 예제

예 :

ActiveRecord::Base.transaction do
  david.withdrawal(100)
  mary.deposit(100)
end

이 예는 오직 다윗에게서 돈을 가져다가 인출이나 예금으로 예외를 두지 않으면 마리아에게 준다. 예외는 트랜잭션이 시작되기 전의 상태로 데이터베이스를 리턴하는 ROLLBACK을 강제 실행합니다. 그러나 객체의 인스턴스 데이터는 트랜잭션 전 상태로 반환되지 않습니다.

단일 트랜잭션에서 다른 ActiveRecord 클래스

트랜잭션 클래스 메서드가 일부 ActiveRecord 클래스에서 호출되었지만 트랜잭션 블록 내의 개체가 모두 해당 클래스의 인스턴스 일 필요는 없습니다. 이는 트랜잭션이 모델별로가 아니라 데이터베이스 별 연결이기 때문입니다.

이 예제에서는 계정 클래스에서 트랜잭션이 호출 되더라도 잔액 레코드가 트랜잭션으로 저장됩니다.

Account.transaction do
  balance.save!
  account.save!
end

트랜잭션 메소드는 모델 인스턴스 메소드로 사용할 수도 있습니다. 예를 들어 다음과 같이 할 수도 있습니다.

balance.transaction do
  balance.save!
  account.save!
end

다중 데이터베이스 연결

트랜잭션은 단일 데이터베이스 연결에서 작동합니다. 클래스 별 데이터베이스가 여러 개있는 경우 트랜잭션은 트랜잭션을 상호 작용할 수 없습니다. 한 가지 해결 방법은 모델을 변경 한 각 클래스에서 트랜잭션을 시작하는 것입니다.

Student.transaction do
  Course.transaction do
    course.enroll(student)
    student.units += course.units
  end
end

이것은 좋지 않은 솔루션이지만 완전히 분산 된 트랜잭션은 ActiveRecord의 범위를 벗어납니다.

저장 및 삭제는 트랜잭션에서 자동으로 래핑됩니다.

#save와 #destroy 모두 트랜잭션에 랩핑되어 검증 또는 콜백에서 수행하는 작업이 보호 대상에서 수행되도록 보장합니다. 따라서 유효성 검사를 사용하여 트랜잭션이 의존하는 값을 확인하거나 after_* 콜백을 포함하여 롤백에 대한 콜백에서 예외를 발생시킬 수 있습니다.

따라서 작업이 완료 될 때까지 데이터베이스 외부의 변경 내용이 표시되지 않습니다. 예를 들어, after_save 에서 검색 엔진 색인을 업데이트하려고하면 인덱서는 업데이트 된 레코드를 보지 않습니다. after_commit 콜백은 업데이트가 커밋 된 후에 트리거됩니다.

콜백

트랜잭션을 커밋하고 롤백하는 것과 관련된 두 가지 유형의 콜백 ( after_commitafter_rollback 있습니다.

after_commit 콜백은 트랜잭션이 커밋 된 직후 트랜잭션 내에서 저장되거나 소멸되는 모든 레코드에서 호출됩니다. after_rollback 콜백은 트랜잭션 또는 세이브 포인트가 롤백 된 직후 트랜잭션 내에서 저장되거나 파괴 된 모든 레코드에서 호출됩니다.

이러한 콜백은 데이터베이스가 영구적 인 상태 일 때만 콜백이 실행된다는 것을 보장하므로 다른 시스템과 상호 작용할 때 유용합니다. 예를 들어, after_commit 은 트랜잭션 내에서 캐시를 지우면 데이터베이스가 업데이트되기 전에 캐시가 재생성 될 수 있기 때문에 캐시를 지우는 데 적합합니다.

트랜잭션 롤백

ActiveRecord::Base.transactionActiveRecord::Rollback 예외를 사용하여 의도하지 않은 롤백을 다른 예외 상황과 구별합니다. 일반적으로 예외를 발생 시키면 .transaction 메서드가 데이터베이스 트랜잭션을 롤백하고 예외를 전달합니다. 그러나 ActiveRecord::Rollback 예외를 발생 시키면 예외를 ActiveRecord::Rollback 않고 데이터베이스 트랜잭션이 롤백됩니다.

예를 들어, 컨트롤러에서 트랜잭션을 롤백 할 수 있습니다.

class BooksController < ActionController::Base
  def create
    Book.transaction do
      book = Book.new(params[:book])
      book.save!
      if today_is_friday?
        # The system must fail on Friday so that our support department
        # won't be out of job. We silently rollback this transaction
        # without telling the user.
        raise ActiveRecord::Rollback, "Call tech support!"
      end
    end
    # ActiveRecord::Rollback is the only exception that won't be passed on
    # by ActiveRecord::Base.transaction, so this line will still be reached
    # even on Friday.
    redirect_to root_url
  end
end


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow