[Firestore] 7편 - transaction/ batched write
https://firebase.google.com/docs/firestore/manage-data/transactions?authuser=0
1. Transaction: 하나 이상의 문서에 대한 read, write 작업 집합
2. Batched write: 하나 이상의 문서에 대한 write 작업 집합
Firestore는 atomic operation을 지원한다. 묶음 작업에 해당하는 것 전체가 실패하거나, 전체가 성공한다.
(전체 작업중 일부분만 작업이 처리되지 않는다)
묶음 작업중 하나라도 보안룰을 만족하지 않으면 모두 실패된다.
- Transaction
Transaction클래스의 delete, get, set, update 메서드를 사용한다.
이전 포스팅에서 사용했던 작업 메서드처럼 작업하는데 ,어떤 문서인지 추가적인 DocumentReference 인자를 넣어준다.
또한 쿼리와 일반 문서 get과 다르게 리턴타입이 Task가 아니라 스냅샷이다.
예를 들면 트랜잭션이 특정 문서를 읽는 동안 다른 클라이언트에서 문서를 수정하면, 트랜잭션 전체를 재시도한다.
트랜잭션 사용시 주의사항
1. read집합이 write집합보다 먼저 나와야 한다.
2. 트랜잭션에서 읽고 있는 문서에 동시에 문서 수정이 이루어지는 경우 트랜잭션(트랜잭션 함수)이 여러번 재 실행될 수 있다.
3. 트랜잭션 함수내에서 어플리케이션 상태를 직접 수정해서는 안된다(should not)
데이터 일관성 문제가 발생할 수 있다.
4. 클라이언트가 오프라인이면 트랜잭션이 실패한다.
트랜잭션이 실패하는 경우
1. write작업 후에 read작업들이 존재하는 경우
2. 트랜잭션 바깥에서 수정되고 있는 문서를 트랜잭션이 읽는 경우. 이 경우 트랜잭션이 자동으로 재실행된다.
몇번이고 재실행될 수 있다.
3. maximum request size of 10 MiB 를 초과한 경우
실패한 트랜잭션은 에러를 리턴하고 데이터베이스에 아무 write작업을 하지 않는다.
roll back할 필요가 없이 Firestore가 자동으로 해준다.
- batched write
묶음 작업에 문서 read작업이 필요하지 않는경우 사용
트랜잭션과 동일하게 atomic operation을 지원한다.
트랜잭션과 다르게 read작업이 없으므로 실패할 가능성이 더 낮다.
batched write는 클라이언트가 오프라인인 경우에도 진행된다.
https://firebase.google.com/docs/firestore/transaction-data-contention
트랜잭션이 성공하기 위해서는
트랜잭션의 read operation에서 읽히는 문서들은, 외부 operation들에 의해 수정되지 않는 상태를 유지해야 한다.
다른 operation이 이러한 문서들은 수정하려고 시도하면, 그 operation이 transaction의 data contention 상태로 들어간다.
data contention
두개 이상의 operation들이 같은 문서를 컨트롤하려고 경쟁하는 상태
동시 진행되는 operation은 문서의 필드를 업데이트하려는 반면 특정 트랜잭션에서 일관된 문서 상태를 유지 해야할 수도 있다.
Firestore는 이러한 operation들중 하나를 지연하거나, 실패함으로서 data contention 문제를 해결한다.
클라이언트 라이브러리는 data contention으로인해 실패한 트랜잭션들을 자동으로 재시도한다.
몇번의 재시도를 통한 후 실패하면 에러메세지를 리턴한다.
어떠한 operation들을 실패처리, 지연시킬지는 클라이언트 라이브러리에 따라 다르다.
모바일의 경우 optimistic concurrency control 사용
서버 클라이언트 라이브러리는 서버가 없기 때문에 생략...
https://en.wikipedia.org/wiki/Optimistic_concurrency_control
Optimistic concurrency control (OCC), also known as optimistic locking
(문서에 lock을 걸지않고 모든 작업 완료후 commit전에 다른놈이 건드리면 commit하지 않고 트랜잭션 재실행하여 재차체킹-> 다른놈이 안건드렸으면 commit)
OCC는 여러 트랜잭션들이 서로간에 영향을 주지 않고 작업이 완료될 수 있다는 것을 가정한다.
리소스에 대한 lock을 사용하지 않고 데이터 리소스만 사용한다. 모든 작업을 끝내놓고 commit하기 전에 현재 트랜잭션에 해당하는 데이터를 다른 트랜잭션들이 건드렸을 경우 commit하지 않고 재실행된다.
data contention이 적은 환경에서 일반적으로 사용된다.
Pessimistic concurrency controls
(data contention이 자주 일어난다 가정하는 동시성 컨트롤. 문서에 lock을 걸어 진행)
Serializable isolation by commit time
Firestore는 각 트랜잭션에 commit 타임을 기록한다.
트랜잭션의 작업은 실제로 짧은 시간동안 진행되지만, 트랜잭션 내부의 모든 read,write 작업들은 정확히 트랜잭션 commit 타임에 발생했다고 가정한다.