MongoDB 데이터베이스 2 단계 제출 실현 방법 상세 설명

9346 단어 MongoDB사무.
이 글 의 사례 는 MongoDB 데이터베이스 2 단계 에서 사 무 를 실현 하 는 방법 을 제출 하 는 것 을 다 루 었 다.여러분 께 참고 하도록 공유 하 겠 습 니 다.구체 적 으로 는 다음 과 같 습 니 다.
MongoDB 데이터베이스 에서 하나의 문 서 를 조작 하 는 것 은 항상 원자 적 이지 만 여러 문서 와 관련 된 작업 은 원자 적 인 것 이 아니 라'사무'로 여 겨 진다.문 서 는 상당히 복잡 하고 여러 개의 포 함 된 문 서 를 포함 할 수 있 기 때문에 단일 문서 의 원자 성 은 많은 실제 사례 에 지원 을 제공 합 니 다.단일 문서 작업 은 원자 적 이지 만 어떤 경우 에는 다 중 문서 작업 이 필요 합 니 다.이러한 상황 에서 2 단계 제출 을 사용 하여 이러한 유형의 다 중 문서 업데이트 지원 을 제공 합 니 다.문 서 는 Pending 데이터 와 상 태 를 표시 할 수 있 기 때문에 두 단계 로 제출 하여 데이터 가 일치 하 는 지 확인 할 수 있 습 니 다.잘못된 경우 트 랜 잭 션 전 상 태 를 복구 할 수 있 습 니 다.
사무 에서 가장 흔히 볼 수 있 는 예 는 신뢰 할 수 있 는 방식 으로 A 계 정 에서 B 계 정 으로 이체 하 는 것 이다.관계 형 데이터베이스 에서 이 조작 은 A 계 정 에서 금액 을 줄 이 고 B 계 정 에 금액 을 늘 리 는 조작 을 하나의 원자 사무 에 봉인 한다.몽고 DB 에 서 는 2 단계 제출 을 사용 해 같은 효 과 를 낼 수 있다.본 논문 의 모든 예제 에 서 는 mongo 셸 과 데이터 베 이 스 를 사용 하여 상호작용 을 하고 두 개의 집합 이 있다 고 가정 합 니 다.먼저,accounts 라 는 집합 은 각 계 정의 문서 데 이 터 를 저장 하고 다른 하 나 는 transactions 라 는 집합 저장 사무 자 체 를 저장 합 니 다.
먼저 A 와 B 라 는 계 정 을 만 들 고 다음 명령 을 사용 합 니 다.

db.accounts.save({name: "A", balance: 1000, pendingTransactions: []})
db.accounts.save({name: "B", balance: 1000, pendingTransactions: []})

find()방법 을 사용 하여 이 두 조작 이 이미 성공 했다 는 것 을 검증 합 니 다.

db.accounts.find()

mongo 는 다음 과 같은 두 개의 문 서 를 되 돌려 줍 니 다.

{ "_id" : ObjectId("4d7bc66cb8a04f512696151f"), "name" : "A", "balance" : 1000, "pendingTransactions" : [ ] }
{ "_id" : ObjectId("4d7bc67bb8a04f5126961520"), "name" : "B", "balance" : 1000, "pendingTransactions" : [ ] }

트 랜 잭 션 프로 세 스:
트 랜 잭 션 초기 상태 초기 설정:
아래 문 서 를 삽입 하여 transaction 집합 을 만 듭 니 다.transaction 문 서 는 원본(source)과 대상(destination)을 가지 고 있 습 니 다.accounts 집합 문서 의 필드 이름과 value 필드 를 참조 하여 balance 필드 의 수량 을 바 꾸 는 데 이 터 를 표시 합 니 다.마지막 으로 state 필드 는 현재 상 태 를 반영 합 니 다.
db.transactions.save({source: "A", destination: "B", value: 100, state: "initial"})
이 조작 이 성공 적 으로 검증 되 었 습 니 다.사용find():

db.transactions.find()

이 동작 은 다음 과 같은 문 서 를 되 돌려 줍 니 다.
{ "_id" : ObjectId("4d7bc7a8b8a04f5126961522"), "source" : "A", "destination" : "B", "value" : 100, "state" : "initial" }
Pending 상태 로 트 랜 잭 션 전환:
accounts 집합 기록 을 수정 하기 전에 트 랜 잭 션 상 태 를 initial 에서 pending 으로 설정 합 니 다.findOne()방법 을 사용 하여 transaction 문 서 를 셸 세 션 의 부분 변수 t 에 할당 합 니 다.

t = db.transactions.findOne({state: "initial"})

변수 t 가 생 성 되면 셸 은 값 을 되 돌려 줍 니 다.다음 출력 을 볼 수 있 습 니 다.
{ "_id" : ObjectId("4d7bc7a8b8a04f5126961522"), "source" : "A", "destination" : "B", "value" : 100, "state" : "initial" }
update()state 의 값 을 pending 으로 변경 합 니 다.

db.transactions.update({_id: t._id}, {$set: {state: "pending"}})
db.transactions.find()

find()작업 은 transaction 집합 내용 을 되 돌려 줍 니 다.다음 과 같 습 니 다.
{ "_id" : ObjectId("4d7bc7a8b8a04f5126961522"), "source" : "A", "destination" : "B", "value" : 100, "state" : "pending" }
두 계 정 에 트 랜 잭 션 적용:update()방법 으로 두 계 정 에 사 무 를 적용 합 니 다.update()조회 에서 조건pendingTransactions:{$ne:t._id}이 트 랜 잭 션 계 정 업 데 이 트 를 막 습 니 다.계 정의 pendingTransaction 필드 에 트 랜 잭 션 t 가 포함 되 어 있 는id:

db.accounts.update(
 { name: t.source, pendingTransactions: { $ne: t._id } },
 { $inc: { balance: -t.value }, $push: { pendingTransactions: t._id } }
)
db.accounts.update(
 { name: t.destination, pendingTransactions: { $ne: t._id } },
 { $inc: { balance: t.value }, $push: { pendingTransactions: t._id } }
)
db.accounts.find()

find()조작 은 accounts 집합 내용 을 되 돌려 줍 니 다.지금 은 다음 과 유사 해 야 합 니 다.

{ "_id" : ObjectId("4d7bc97fb8a04f5126961523"), "balance" : 900, "name" : "A", "pendingTransactions" : [ ObjectId("4d7bc7a8b8a04f5126961522") ] }
{ "_id" : ObjectId("4d7bc984b8a04f5126961524"), "balance" : 1100, "name" : "B", "pendingTransactions" : [ ObjectId("4d7bc7a8b8a04f5126961522") ] }

트 랜 잭 션 상 태 를 committed 로 설정:
아래update()작업 설정 사 무 를 사용 하 는 상 태 는 committed 입 니 다.

db.transactions.update({_id: t._id}, {$set: {state: "committed"}})
db.transactions.find()

find()transactions 집합 내용 을 조작 하여 다음 과 유사 해 야 합 니 다.
{ "_id" : ObjectId("4d7bc7a8b8a04f5126961522"), "destination" : "B", "source" : "A", "state" : "committed", "value" : 100 }
pending 트 랜 잭 션 제거:
아래update()동작 을 사용 하여 accounts 집합 에서 pending 사 무 를 제거 합 니 다.

db.accounts.update({name: t.source}, {$pull: {pendingTransactions: t._id}})
db.accounts.update({name: t.destination}, {$pull: {pendingTransactions: t._id}})
db.accounts.find()

find()accounts 집합 내용 을 되 돌려 줍 니 다.지금 은 다음 과 유사 해 야 합 니 다.

{ "_id" : ObjectId("4d7bc97fb8a04f5126961523"), "balance" : 900, "name" : "A", "pendingTransactions" : [ ] }
{ "_id" : ObjectId("4d7bc984b8a04f5126961524"), "balance" : 1100, "name" : "B", "pendingTransactions" : [ ] }

트 랜 잭 션 상 태 를 done 으로 설정 합 니 다:
transaction 문 서 를 설정 한 state 를 통 해 done 으로 업 무 를 완성 합 니 다:

db.transactions.update({_id: t._id}, {$set: {state: "done"}})
db.transactions.find()

find()transaction 집합 내용 을 되 돌려 줍 니 다.이 때 는 다음 과 같 아야 합 니 다.
{ "_id" : ObjectId("4d7bc7a8b8a04f5126961522"), "destination" : "B", "source" : "A", "state" : "done", "value" : 100 }
실패 필드 에서 회복:
가장 중요 한 부분 은 위의 전형 적 인 예 가 아니 라 각종 실패 장면 에서 미 완성 사 무 를 회복 할 가능성 이다.이 부분 은 가능 한 실 패 를 개술 하고 이 사건 들 에서 업 무 를 회복 하 는 방법 을 제공 할 것 이다.여기에 두 가지 유형의 실패 가 있다.
1.모든 것 은 첫 번 째 단계(즉,트 랜 잭 션 의 초기 상태 initial 설정)이후 에 발생 하지만 세 번 째 단계(즉,트 랜 잭 션 을 두 계 정 에 적용 하 는 것)전에 실 패 했 습 니 다.사 무 를 복원 하기 위해 서 는 pending 상태의 transaction 목록 을 가 져 오고 두 번 째 단계(즉,사 무 를 pending 상태 로 전환 하 는 것)에서 복원 해 야 합 니 다.
2.모든 것 은 세 번 째 단계 이후(즉,두 계 정 에 사 무 를 적용 하 는 것)에 발생 하지만 다섯 번 째 단계(즉,사무 상 태 를 done 으로 설정 하 는 것)전에 실 패 했 습 니 다.트 랜 잭 션 을 복원 하기 위해 서 는 committed 상태의 트 랜 잭 션 목록 을 가 져 오고 네 번 째 단계(즉,pending 트 랜 잭 션 제거)에서 복원 해 야 합 니 다.
따라서 응용 프로그램 은 항상 업 무 를 회복 하고 최종 적 으로 일치 하 는 상태 에 이 를 수 있다.프로그램 이 완료 되 지 않 은 모든 사 무 를 캡 처 할 때 아래 의 복구 작업 을 실행 합 니 다.데이터 가 일치 하 는 상 태 를 확보 하기 위해 정기 적 으로 복구 작업 을 실행 하 기 를 원할 수도 있다.일치 상태 에 도달 하 는 데 걸 리 는 시간 은 프로그램 이 모든 업 무 를 복구 하 는 데 얼마나 걸 리 느 냐 에 달 려 있다.
스크롤 백:
어떤 경우 에는'스크롤 백'이나'취소'가 필요 할 수 있 습 니 다.프로그램 이'취소'가 필요 할 때,계 정 이 존재 하지 않 을 때,기 존 업 무 를 영원히 복구 하거나 중지 해 야 하기 때 문 입 니 다.여기에 두 가지 가능 한 스크롤 백 작업 이 있 습 니 다.
1.업무(즉,세 번 째 단계)를 응용 한 후에 당신 은 이미 사 무 를 완전히 제출 했 습 니 다.사 무 를 되 돌려 서 는 안 됩 니 다.반대로 새로운 사 무 를 만 들 고 원본(원본)과 대상(destination)의 값 을 전환 합 니 다.
2.트 랜 잭 션(즉 첫 번 째 단계)을 만 든 후 트 랜 잭 션(즉 세 번 째 단계)을 사용 하기 전에 아래 의 처리 과정 을 사용 합 니 다.
트 랜 잭 션 상 태 를 canceling 으로 설정 합 니 다:
우선 트 랜 잭 션 상 태 를 canceling 으로 설정 하고 아래update()동작 을 사용 합 니 다.

db.transactions.update({_id: t._id}, {$set: {state: "canceling"}})

트 랜 잭 션 취소:
다음 작업 순 서 를 사용 하여 두 계 정 에서 사 무 를 취소 합 니 다.

db.accounts.update({name: t.source, pendingTransactions: t._id}, {$inc: {balance: t.value}, $pull: {pendingTransactions: t._id}})
db.accounts.update({name: t.destination, pendingTransactions: t._id}, {$inc: {balance: -t.value}, $pull: {pendingTransactions: t._id}})
db.accounts.find()

find()acounts 집합 으로 돌아 가 는 내용 은 다음 과 같 아야 합 니 다.

{ "_id" : ObjectId("4d7bc97fb8a04f5126961523"), "balance" : 1000, "name" : "A", "pendingTransactions" : [ ] }
{ "_id" : ObjectId("4d7bc984b8a04f5126961524"), "balance" : 1000, "name" : "B", "pendingTransactions" : [ ] }

트 랜 잭 션 상 태 를 canceled 로 설정 합 니 다:
마지막 으로 아래update()상 태 를 사용 하여 트 랜 잭 션 상 태 를 canceled 로 설정 합 니 다.

db.transactions.update({_id: t._id}, {$set: {state: "canceled"}})

참고 자료:http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits/
본 고 에서 말 한 것 이 여러분 의 MongoDB 데이터베이스 프로 그래 밍 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기