v4 이전에 MongoDB가 ACID를 준수하지 않는 것은 실제로 무엇을 의미 했습니까?


226

나는 데이터베이스 전문가가 아니며 공식적인 컴퓨터 과학 배경이 없으므로 나와 함께하십시오. ACID와 호환 되지 않는 v4 이전 의 이전 MongoDB 버전 을 사용하는 경우 발생할 수있는 실제 부정적인 종류에 대해 알고 싶습니다 . 이것은 모든 ACID 비준수 데이터베이스에 적용됩니다.

MongoDB는 Atomic Operations를 수행 할 수 있지만 성능상의 이유로 "전통적인 잠금 및 복잡한 트랜잭션"을 지원하지 않는다는 것을 알고 있습니다. 또한 데이터베이스 트랜잭션의 중요성과 데이터베이스가 은행을위한 경우의 예를 이해하고 모두 동기화해야하는 여러 레코드를 업데이트하는 경우 트랜잭션이있는 경우 트랜잭션이 초기 상태로 되돌아 가기를 원합니다. 정전으로 인해 신용은 구매 등과 같습니다.

그러나 MongoDB에 대한 대화를 할 때 데이터베이스가 실제로 어떻게 구현되는지에 대한 기술적 세부 사항을 모르는 사람들은 다음과 같은 문장을 던지기 시작합니다.

MongoDB는 MySQL 및 Postgres보다 훨씬 빠르지 만 1 백만 분의 1과 같이 "올바르게 저장되지 않을"가능성은 적습니다.

"정확하게 저장하지 않습니다"부분은 이러한 이해를 언급합니다. MongoDB에 쓰는 순간 정전이 발생하면 특정 기록이있을 수 있습니다 (예 : 10 개의 속성이있는 문서에서 페이지 뷰를 추적하고 있음) 각각), 문서 중 하나는 5 개의 속성 만 저장했습니다. 이는 시간이지나면서 페이지 뷰 카운터가 "약간"꺼질 것임을 의미합니다. 당신은 그들이 얼마나 99.999 %이지만 100 %가 아니라는 것을 알지 못할 것입니다. 이것은 특별히 mongodb atomic operation으로 설정하지 않는 한 조작이 원자적임을 보장하지 않기 때문입니다.

제 질문은 MongoDB가 "올바르게 저장되지"않을시기와 이유에 대한 올바른 해석은 무엇입니까? ACID의 어떤 부분이 만족스럽지 않으며 어떤 상황에서 데이터의 0.001 %가 꺼져 있는지 어떻게 알 수 있습니까? 어떻게 든 고칠 수 없습니까? 그렇지 않은 경우 users레코드가 저장되지 않을 수 있으므로 테이블 과 같은 것을 MongoDB에 저장해서는 안된다는 의미입니다 . 그러나 다시 한 번 1 / 1,000,000 명의 사용자는 "다시 가입을 시도"해야합니다.

MongoDB와 같은 ACID 비 호환 데이터베이스에서 부정적 일이 발생하는시기 / 이유 목록을 찾고 있으며 이상적으로 표준 해결 방법이있는 경우 (데이터를 정리하기 위해 백그라운드 작업을 실행하거나이를 위해 SQL 만 사용하는 등) 이상적입니다. .

답변:


133

MongoDB에서 잃어버린 한 가지는 다중 수집 (테이블) 트랜잭션입니다. MongoDB의 원자 수정자는 단일 문서에 대해서만 작동 할 수 있습니다.

재고에서 품목을 제거하고 동시에 다른 사람의 주문에 추가해야하는 경우에는 할 수 없습니다. 재고와 주문이라는 두 가지가 동일한 문서에 존재하지 않는 한 (아마도 그렇지 않을 수도 있음)

작업중 인 응용 프로그램 에서이 같은 문제가 발생하여 선택할 수있는 두 가지 가능한 솔루션이 있습니다.

1) 가능한 한 문서를 최대한 구성하고 원자 수정자를 최대한 사용하고 나머지 비트는 백그라운드 프로세스를 사용하여 동기화되지 않은 레코드를 정리하십시오. 예를 들어, 인벤토리에서 항목을 제거하고 원자 수정자를 사용하여 동일한 문서의 reservedInventory 배열에 항목을 추가합니다.

이렇게하면 고객이 예약 한 품목이기 때문에 재고에서 품목을 사용할 수 없음을 항상 알 수 있습니다. 고객이 체크 아웃하면 reservedInventory에서 품목을 제거합니다. 그것은 표준 거래가 아니며 고객이 장바구니를 버릴 수 있기 때문에 버려진 장바구니를 찾아 예약 된 재고를 사용 가능한 재고 풀로 다시 옮기는 백그라운드 프로세스가 필요합니다.

이것은 이상적이지는 않지만 mongodb가 필요에 완벽하게 맞지 않는 큰 응용 프로그램의 유일한 부분입니다. 또한 지금까지 완벽하게 작동합니다. 이것은 많은 시나리오에서 가능하지는 않지만 사용중인 문서 구조로 인해 적합합니다.

2) MongoDB와 함께 트랜잭션 데이터베이스를 사용하십시오. MongoDB (또는 다른 NoSQL)가 최선을 다하는 것을 허용하면서 MySQL을 사용하여 절대적으로 필요한 것에 대한 트랜잭션을 제공하는 것이 일반적입니다.

# 1의 솔루션이 장기적으로 작동하지 않으면 MongoDB를 MySQL과 결합하는 방법에 대해 더 조사 할 것이지만 현재 # 1은 내 요구에 잘 맞습니다.


27
" MongoDB의 원자 수정자는 단일 콜렉션에 대해서만 작동 할 수 있습니다. "=> "단일 문서 에 대한 것"을 의미한다고 생각합니다 .
assylias

2
훌륭한 정보, 일반적으로 MySQL 사용을 제안하는 것을 제외하고는 훌륭한 답변입니다.
Doug Molineux

MongoDB에서 잃어버린 한 가지는 다중 수집 (테이블) 트랜잭션입니다. MongoDB의 원자 수정자는 mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ) 의 단일 문서에 대해서만 작동 할 수 있습니다 . ""MongoDB에서 쓰기 작업은 단일 레벨의 원자 작업이 단일 문서 내에서 여러 개의 포함 된 문서를 수정하더라도 "
yoav.str

5
다중 문서 ACID 트랜잭션 부족은 더 이상 해당되지 않습니다. MongoDB는 v4.0에서 출시 될 것이라고 발표했다. mongodb.com/blog/post/multi-document-transactions-in-mongodb
Grigori Melnik

1
현재 MongoDB 4.0은 다중 문서 트랜잭션을 가진 ACID 호환 mongodb.com/transactions 입니다. 한 번 봐 가지고 mongodb.com/blog/post/...
Ratah

134

MongoDB가 ACID를 준수하지 않는 것은 실제로 올바르지 않습니다. 반대로 MongoDB는 문서 수준에서 ACID- 컴파일러입니다 .

단일 문서에 대한 모든 업데이트는

  • 원자 : 그것은 완전히 완료되거나 그렇지 않습니다
  • 일관된 : "부분적으로 적용된"업데이트를 읽는 독자가 없습니다.
  • 격리 됨 : 다시 말하지만 독자는 "더러운"판독 값을 볼 수 없습니다
  • 내구성 : (적절한 쓰기 관련)

MongoDB에없는 것은 트랜잭션 입니다. 롤백 할 수 있고 ACID를 준수하는 다중 문서 업데이트입니다.

2 단계 커밋사용하여 단일 문서에 대한 ACID 호환 업데이트를 기반으로 트랜잭션을 빌드 할 수 있습니다 .


3
2 단계 커밋 트랜잭션은 ACID를 준수하지 않습니다. 어떤 이유로 나는 링크를 따라갈 때까지 그 반대를 추론했다.
Justin C

1
쓰기 문제 구성에 관계없이 문서 수준에서 분산 MongoDB의 내구성에 대한 몇 가지 질문이 있습니다. 오픈 소스 도구 인 Jepsen은 대규모 쓰기 문제가 있어도 네트워크 파티션에서 데이터가 손실 될 수 있음을 발견했습니다. 글을 참고하세요 : aphyr.com/posts/284-call-me-maybe-mongodb
jrullmann

9
RDBMS의 단일 레코드에 해당하는 단일 문서 레벨의 ACID를 갖는 것은 많은 경우에 유용하지 않습니다. 트랜잭션 용어는 단일 테이블과 관련이 없으며, 2 단계 커밋 메커니즘을 가질 수 있으며 여러 XAResource를 포함 할 수 있으므로 단일 문서를 ACID 호환이 다소 문제가되므로 IMHO라고합니다.
Yair Zaslavsky

5
Yair에 동의하십시오. "문서 수준의 ACID 호환"은 판매 지점이 아닙니다. 기본적으로 "ACID 호환이 아님"을 의미합니다. ACID는 결코 "단지 하나의 행 / 문서 / 엔티티"가되어서는 안됩니다. 전체 데이터베이스에서 데이터 일관성을 유지하는 것입니다.
joshua.paling

34

"Starbucks는 2 단계 커밋을 사용하지 않습니다"에 좋은 설명이 있습니다 .

NoSQL 데이터베이스에 관한 것이 아니라 때때로 트랜잭션이 손실되거나 데이터베이스가 일시적으로 일관성이없는 상태가 될 수있는 시점을 보여줍니다.

나는 그것이 "고정"될 필요가 있다고 생각하지 않을 것이다. 수정은 ACID 호환 관계형 데이터베이스를 사용하는 것입니다. 동작이 애플리케이션 요구 사항을 충족 할 경우 NoSQL 대안을 선택합니다.


1
다른 비유와 마찬가지로 제한이 있습니다. 소프트웨어에서는 새로운 Array [Cashiers]를 쉽게 생성하고 각각의 동기 트랜잭션을 처리하는 것이 쉽지만 실제 비용은 엄청나게 비쌉니다.
HRJ December

16

다른 사람들이 이미 좋은 대답을했다고 생각합니다. 그러나 ACID NOSQL DB (예 : http://ravendb.net/ ) 가 있음을 추가하고 싶습니다 . 따라서 결정은 NOSQL뿐만 아니라 ACID와 ACID의 관계도 없습니다.


1
감사합니다 @subGate. ravenDB와 경험을 공유하고 실제로 요구 사항을 충족하는 사람이 있습니까?
Nir Pengas

12

"올바로 저장하지 않는다"는 의미는 다음과 같습니다.

  1. 기본적으로 MongoDB는 변경 사항을 드라이브에 즉시 저장하지 않습니다. 따라서 사용자에게 "업데이트 성공"을 알리고 정전이 발생하여 업데이트가 유실 될 수 있습니다. MongoDB는 업데이트 수준 "내구성"을 제어하는 ​​옵션을 제공합니다. 다른 복제본이 메모리에서이 업데이트를 수신 할 때까지 기다리거나 로컬 저널 파일에 대한 쓰기가 수행 될 때까지 기다릴 수 있습니다.

  2. 여러 모음에 대한 쉬운 "원자"업데이트는 없으며 동일한 모음에있는 여러 문서까지도 없습니다. Two Phase Commit 으로 우회 하거나 스키마를 재구성하여 단일 문서를 업데이트 할 수 있기 때문에 대부분의 경우 문제가되지 않습니다 . 이 질문을 참조하십시오 : 문서 데이터베이스 : 중복 데이터, 참조 등 (MongoDB)


10

MongoDB v4.0부터 다중 문서 ACID 트랜잭션이 지원됩니다. 스냅 샷 격리를 통해 트랜잭션은 전 세계적으로 일관된 데이터보기를 제공하고 데이터 무결성을 유지하기 위해 전혀 또는 전혀 실행하지 않습니다.

그들은 다음과 같은 관계 세계의 거래처럼 느껴집니다.

with client.start_session() as s:
    s.start_transaction()
    try:
        collection.insert_one(doc1, session=s)
        collection.insert_one(doc2, session=s)
        s.commit_transaction()
    except Exception:
        s.abort_transaction()

https://www.mongodb.com/blog/post/multi-document-transactions-in-mongodb를 참조 하십시오.


MongoDB4.0의 첫 번째 릴리스 후보가 밖으로 - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
그리고 리 MELNIK

5

더 나은 이해를 위해 ACID 속성 에 대해 읽으십시오 .

또한 MongoDB 문서에서 질문과 답변을 찾을 수 있습니다 .

MongoDB는 ACID를 준수하지 않습니다. ACID 준수에 대한 설명은 아래를 참조하십시오.

  1. MongoDB는 A문서 수준에서만 토믹합니다. 관계형 데이터베이스 시스템, 특히 위의 링크에서 아는 원자의 정의를 준수하지 않습니다. 이런 의미에서 MongoDB는 ACID의 A를 준수하지 않습니다.
  2. MongoDB는 C기본적으로 온 사이트입니다. 그러나 복제본 세트의 보조 서버에서 읽을 수 있습니다 . 이 경우 최종 일관성가질 수 있습니다 . 약간 오래된 데이터를 읽지 않아도되는 경우에 유용합니다.
  3. MongoDB는 I위의 정의에 따라 격리를 보장하지 않습니다 .
  1. 동시 판독기와 기록기가 여러 개인 시스템의 경우 MongoDB는 클라이언트가 쓰기 작업이 반환되기 전에 쓰기 작업 결과를 읽을 수 있도록합니다.
  2. 저널이 커미트하기 전에 mongod가 종료되면 쓰기가 성공적으로 리턴 되더라도 쿼리가 mongod가 다시 시작된 후 존재하지 않는 읽기 데이터를 가질 수 있습니다.

그러나 MongoDB는 (삽입 및 업데이트를 위해) 각 문서를 개별적으로 수정합니다. 다중 문서 트랜잭션이 아닌 문서 레벨에서만.

  1. D내구성 과 관련하여 - write concern확실하지 않은 옵션 으로이 동작을 구성 할 수 있습니다 . 아마 누군가가 더 잘 알고있을 것입니다.

NoSQL을 ACID 제약 또는 이와 유사한 것으로 옮기려는 일부 연구가 진행되고 있다고 생각합니다. NoSQL 데이터베이스는 일반적으로 빠르며 ACID 제약으로 인해 성능이 크게 느려질 수 있으므로 문제가됩니다.


4

원자가 단일 콜렉션에 대해 작업을 수정하는 유일한 이유는 mongodb 개발자가 최근 데이터베이스 잠금을 콜렉션 전체 쓰기 잠금과 교환했기 때문입니다. 여기에서 증가 된 동시성을 결정하는 것은 그만한 가치가 있습니다. 핵심적으로 mongodb는 메모리 매핑 된 파일입니다. 이들은 버퍼 풀 관리를 시스템의 vm 하위 시스템에 위임했습니다. 항상 메모리에 저장되어 있기 때문에 매우 정교하게 잠금을 해제 할 수 있습니다. 메모리를 잡고있는 동안 만 메모리 내 작업을 수행하므로 매우 빠릅니다. 이것은 페이지 록이나 행록을 유지하면서 때때로 I / O를 수행해야하는 기존 데이터베이스 시스템과 크게 다릅니다.


이것이 동시성을 증가시키는 이유를 설명해 주시겠습니까? 내가 여기서 명백한 것을 놓친다면 죄송합니다.
batbrat

@batbrat : 동일한 데이터베이스의 다른 컬렉션에 동시에 쓰려고하는 두 클라이언트를 고려하십시오. 데이터베이스 잠금을 사용하면 클라이언트 중 하나가 쓰기를 수행하기 전에 다른 클라이언트가 완료 될 때까지 기다려야합니다. 컬렉션 잠금을 사용하면 두 클라이언트가 동시에 쓸 수 있습니다. 이것이 동시성 향상이라는 의미입니다. 물론 두 클라이언트가 모두 같은 컬렉션에 쓰려고하면 기다려야합니다.
jrullmann

2

"MongoDB에서 단일 문서에 대한 작업은 원자 적입니다"- 과거의 일

새로운 버전의 MongoDB 4.0에서는 다음을 수행 할 수 있습니다.

그러나 여러 문서에 대한 업데이트 또는 여러 문서에 대한 읽기 간 일관성에 원 자성이 필요한 상황에서는 MongoDB는 복제 세트에 대해 다중 문서 트랜잭션을 수행 할 수있는 기능을 제공합니다. 다중 문서 트랜잭션은 여러 작업, 컬렉션, 데이터베이스 및 문서에서 사용될 수 있습니다. 다중 문서 거래는 "전부 또는 전무"제안을 제공합니다. 트랜잭션이 커밋되면 트랜잭션에서 변경된 모든 데이터가 저장됩니다. 트랜잭션의 조작이 실패하면 트랜잭션이 중단되고 트랜잭션에서 작성된 모든 데이터 변경 사항이 표시되지 않고 삭제됩니다. 트랜잭션이 커밋 될 때까지 트랜잭션의 쓰기 작업은 트랜잭션 외부에서 볼 수 없습니다.

에 대한 몇 가지 제한 사항이 있습니다하지만 어떻게 하고 어떤 작업을 수행 할 수 있습니다.

Mongo Doc을 확인하십시오. https://docs.mongodb.com/master/core/transactions/


1

스토리지가 키별 선형성을 지원하고 비교 및 ​​설정하는 경우 (MongoDB에 해당) 클라이언트 측에서 원자 다중 키 업데이트 (직렬화 가능 트랜잭션)를 구현할 수 있습니다. 이 접근 방식은 Google PercolatorCockroachDB 에서 사용되지만 MongoDB와 함께 사용하는 것을 막는 것은 없습니다.

내가 만든 단계별로 시각화 등의 거래를. 이해하는 데 도움이 되길 바랍니다.

읽기 커밋 된 격리 수준에 문제가 없다면 Peter Bailis의 RAMP 트랜잭션 을 살펴 보는 것이 좋습니다. 또한 클라이언트 측에서 MongoDB를 위해 구현 될 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.