트랜잭션
개요
이 가이드에서는 Laravel MongoDB 패키지를 사용하여 MongoDB에서 트랜잭션 을 수행하는 방법을 배울 수 있습니다. 트랜잭션을 사용하면 트랜잭션이 커밋된 후에만 데이터를 업데이트하는 쓰기 작업 시퀀스를 실행할 수 있습니다.
트랜잭션이 실패하면 Laravel MongoDB의 MongoDB 작업을 관리하는 MongoDB PHP 라이브러리는 MongoDB가 트랜잭션 내에서 변경된 내용이 표시되기 전에 모든 변경 사항을 삭제하도록 합니다. 트랜잭션 내의 모든 변경 사항이 적용되거나 삭제되도록 하는 트랜잭션의 이러한 속성을 원자성 이라고 합니다.
MongoDB는 단일 문서에 대해 원자적으로 쓰기 작업을 수행합니다. 여러 문서에 대한 쓰기 작업의 원자성이 필요하거나 작업을 위해 여러 문서의 데이터 일관성이 필요한 경우 다중 문서 트랜잭션에서 실행하세요.
다중 문서 트랜잭션은 ACID를 준수 하는데, MongoDB는 드라이버에 예기치 않은 오류가 발생하더라도 트랜잭션 작업의 데이터가 일관되게 유지되도록 보장하기 때문입니다.
MongoDB 의 트랜잭션에 학습 보려면 서버 매뉴얼에서 트랜잭션 을 참조하세요.
이 가이드 에는 다음 섹션이 포함되어 있습니다.
팁
트랜잭션 학습 바이트
Laravel 트랜잭션 학습 바이트에서 Laravel MongoDB 를 사용하여 트랜잭션을 수행하는 방법을 연습합니다.
요구 사항 및 제한 사항
MongoDB에서 트랜잭션을 수행하려면 다음 MongoDB 버전 및 토폴로지를 사용해야 합니다.
MongoDB 버전 4.0 이상
복제본 세트 배포 또는 샤드 cluster
MongoDB 서버와 Laravel MongoDB에는 다음과 같은 제한 사항이 있습니다.
MongoDB 버전 4.2 이하에서는 트랜잭션 내에서 수행되는 쓰기 작업이 기존 컬렉션에서 이루어져야 합니다. MongoDB 버전 4.4 이상에서는 트랜잭션에서 쓰기 작업을 수행할 때 필요에 따라 서버가 자동으로 컬렉션을 생성합니다. 이 제한에 대해 자세히 알아보려면 매뉴얼 의 트랜잭션에서 컬렉션 및 인덱스 생성 MongoDB Server 을 참조하세요.
MongoDB는 중첩 트랜잭션을 지원하지 않습니다. 다른 트랜잭션 내에서 트랜잭션을 시작하려고 하면 확장 프로그램에서
RuntimeException
가 발생합니다. 이 제한에 대해 자세히 알아보려면 MongoDB Server 매뉴얼의 트랜잭션 및 세션 을 참조하세요.Laravel MongoDB 패키지는 데이터베이스 테스트 특성
Illuminate\Foundation\Testing\DatabaseTransactions
및Illuminate\Foundation\Testing\RefreshDatabase
을 지원하지 않습니다. 이 문제를 해결하려면Illuminate\Foundation\Testing\DatabaseMigrations
트레이트를 사용하여 마이그레이션을 생성하여 각 테스트 후 데이터베이스를 재설정할 수 있습니다.
콜백으로 트랜잭션 실행
이 섹션에서는 콜백에서 트랜잭션을 실행하는 방법을 보여줍니다.
이 메서드를 사용하여 트랜잭션을 실행하면 콜백 메서드의 모든 코드가 단일 트랜잭션으로 실행됩니다.
다음 예제에서 트랜잭션은 Account
모델로 표시되는 은행 계좌에서 다른 계정으로 자금을 이체하는 쓰기 작업으로 구성됩니다.
DB::transaction(function () { $transferAmount = 200; $sender = Account::where('number', 223344)->first(); $sender->balance -= $transferAmount; $sender->save(); $receiver = Account::where('number', 776655)->first(); $receiver->balance += $transferAmount; $receiver->save(); });
다음 코드 예시 와 같이 선택적으로 실패한 트랜잭션 을 재시도할 수 있는 최대 횟수를 두 번째 매개변수로 전달할 수 있습니다.
DB::transaction(function() { // transaction code }, attempts: 5, );
트랜잭션 시작 및 커밋
이 섹션에서는 트랜잭션을 시작하고 커밋하는 방법을 설명합니다.
이 메서드를 사용하여 트랜잭션을 시작하고 커밋하려면 DB::beginTransaction()
메서드를 호출하여 트랜잭션을 시작합니다. 그런 다음 DB::commit()
메서드를 호출하여 트랜잭션을 종료하면 트랜잭션 내에서 수행된 모든 업데이트가 적용됩니다.
다음 예에서는 첫 번째 계정의 잔액을 두 번째 계정으로 이동한 후 첫 번째 계정을 삭제합니다.
DB::beginTransaction(); $oldAccount = Account::where('number', 223344)->first(); $newAccount = Account::where('number', 776655)->first(); $newAccount->balance += $oldAccount->balance; $newAccount->save(); $oldAccount->delete(); DB::commit();
트랜잭션 롤백
이 섹션에서는 트랜잭션을 롤백하는 방법을 보여 줍니다. 롤백은 해당 트랜잭션 내에서 수행된 모든 쓰기 작업을 되돌립니다. 즉, 데이터가 트랜잭션 이전 상태로 되돌아갑니다.
롤백을 수행하려면 트랜잭션이 커밋되기 전에 언제든지 DB::rollback()
함수를 호출합니다.
다음 예제에서 트랜잭션은 Account
모델로 표시되는 한 계정에서 여러 다른 계정으로 자금을 이체하는 쓰기 작업으로 구성됩니다. 발신자 계정에 자금이 충분하지 않으면 트랜잭션이 롤백되고 모델이 업데이트되지 않습니다.
DB::beginTransaction(); $sender = Account::where('number', 223344)->first(); $receiverA = Account::where('number', 776655)->first(); $receiverB = Account::where('number', 990011)->first(); $amountA = 100; $amountB = 200; $sender->balance -= $amountA; $receiverA->balance += $amountA; $sender->balance -= $amountB; $receiverB->balance += $amountB; if ($sender->balance < 0) { // insufficient balance, roll back the transaction DB::rollback(); } else { DB::commit(); }