Mongodb는 쿼리가 실행된 후 찾기 쿼리에서 반환된 커서를 사용하여 데이터 테이블에 새로 추가된 레코드를 탐색합니다(레코드가 많아 쿼리 시간이 오래 걸리고 아직 쿼리가 실행되지 않음).
예:
스레드 A는 find를 사용하여 시점 t1에서 데이터 테이블 사용자를 쿼리하여 커서를 반환하고 데이터 레코드를 탐색합니다.
스레드 B는 삽입을 사용하여 시점 t2에서 데이터 테이블 사용자에 레코드를 삽입합니다.
스레드 B는 시점 t3에서 실행을 완료합니다.
스레드 A는 시점 t4에서 실행을 완료합니다.
시간: t1 < t2 < t4
질문: 스레드 A가 스레드 B가 새로 추가한 레코드를 쿼리할 수 있나요?
매우 좋은 질문입니다. 간단히 말해서 MongoDB는 여러 문서, 심지어 나중에 삽입될 수 있는 문서도 포함하기 때문에 결과에 새 문서가 포함되는지 여부를 보장하지 않습니다. 기존 데이터베이스에서는 새로 삽입된 값을 읽는 것이 가능합니다. 이를 만족할 수 있는 격리 수준은 가장 높은 직렬화 가능(serialized) 수준입니다. 예에서는 두 가지 작업 집합을 한 번 읽습니다. 그리고 하나의 글쓰기가 차례로 수행되는 것 같습니다. 잠금 메커니즘을 구현하는 데 드는 비용도 매우 높으며 성능도 상대적으로 낮습니다. 이 논문을 참조하세요. MongoDB로 돌아가서 MongoDB는 문서를 단위로 사용하고 문서 수준 격리를 보장할 수 있지만 고성능을 대가로 여러 문서 간의 작업 격리(독립성)를 보장하지 않으며 트랜잭션을 지원하지 않습니다.
@huandu가 맞습니다. 테스트할 때
find().batchSize(2)
를 사용하여 각 배치에서 2개의 문서를 읽으면 새로 추가된 문서를 읽을 수 있음을 알 수 있습니다. 셸의 기본 배치 크기는 20인데 이는 관찰하기 쉽지 않을 수 있습니다. 역사적 이유로 인해limit()와 동일한 BatchSize(1)를 사용하지 마십시오.꼭 그렇지는 않습니다.
mongodb 커서는 격리되지 않으며 업데이트된 데이터를 반환할 수 있습니다.
그러나 실제 시도에서는 아무리 삽입해도 새로 삽입된 데이터가 커서로 반환되지 않는 것으로 나타났습니다. 이는 mongodb의 구현 세부 사항일 수도 있고 특정 특수 상황에서만 커서가 새로 삽입된 데이터에 액세스할 수 있을 수도 있습니다. 즉, 문서 지원이 없으므로 이 동작에 의존해서는 안 됩니다.