MongoDB——count不准原因分析

本文分析了MongoDB分片集群中count不准的问题,主要由孤立文档和move chunk期间的数据迁移造成。在3.6版本及以前,count操作可能返回不准确的结果。建议使用aggregate方法获取准确计数,或者在特定场景下调整系统设置以避免数据不一致。同时,文章提供了清理孤立文档的方法和优化count操作的策略。

仅仅是tips,我们用的3.6版本,存在这种情况。4.0版本以后就没了。

背景

一般来说,除了由于secondary延迟可能造成查询secondary节点数据不准以外,关于count的准确性问题,在MongoDB4.0官方文档中有这么一段话
On a sharded cluster, db.collection.count() without a query predicate can result in an inaccurate count iforphaned documents exist or if a chunk migration is in progress.
To avoid these situations, on a sharded cluster, use the db.collection.aggregate() method

而MongoDB3.6官方文档却是这么描述的
On a sharded cluster, db.collection.count() can result in an inaccurate count if orphaned documents exist or if a chunk migration is in progress.
To avoid these situations, on a sharded cluster, use the db.collection.aggregate() method

也就是说,MongoDB4.0分片集群模式下,针对不带谓词条件的全表count操作的返回结果是不准确的,主要包括以下两种场景。在MongoDB4.0以前的版本,即使不带谓词条件,在以下两种场景下count值也不准。
1 存在孤立文档
2 mongo分片集群内部正在进行move chunk操作
本文主要针对这两种场景,分析count不准的原因和规避措施

### 实验目的 了解如何使用 Java 连接 MongoDB 数据库,进行基本的增删改查操作。 ### 实验环境 - JDK 1.8 及以上 - MongoDB 数据库 - Maven 或 Gradle 用于依赖管理 ### 实验步骤 #### 1. 添加依赖 如果使用 Maven,在 `pom.xml` 中添加以下依赖: ```xml <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>4.7.1</version> </dependency> ``` #### 2. 连接 MongoDB ```java import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; public class ConnectToMongoDB { public static void main(String[] args) { // 连接到 MongoDB 服务器 MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017"); // 选择数据库 MongoDatabase database = mongoClient.getDatabase("testdb"); System.out.println("Connected to the database successfully"); } } ``` #### 3. 插入文档 ```java import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import org.bson.Document; public class InsertDocument { public static void main(String[] args) { MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017"); MongoDatabase database = mongoClient.getDatabase("testdb"); MongoCollection<Document> collection = database.getCollection("testcollection"); Document document = new Document("name", "John") .append("age", 30) .append("city", "New York"); collection.insertOne(document); System.out.println("Document inserted successfully"); } } ``` #### 4. 查询文档 ```java import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import org.bson.Document; import com.mongodb.client.FindIterable; public class QueryDocument { public static void main(String[] args) { MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017"); MongoDatabase database = mongoClient.getDatabase("testdb"); MongoCollection<Document> collection = database.getCollection("testcollection"); FindIterable<Document> documents = collection.find(); for (Document document : documents) { System.out.println(document.toJson()); } } } ``` #### 5. 更新文档 ```java import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import org.bson.Document; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; public class UpdateDocument { public static void main(String[] args) { MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017"); MongoDatabase database = mongoClient.getDatabase("testdb"); MongoCollection<Document> collection = database.getCollection("testcollection"); collection.updateOne(Filters.eq("name", "John"), Updates.set("age", 31)); System.out.println("Document updated successfully"); } } ``` #### 6. 删除文档 ```java import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import org.bson.Document; import com.mongodb.client.model.Filters; public class DeleteDocument { public static void main(String[] args) { MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017"); MongoDatabase database = mongoClient.getDatabase("testdb"); MongoCollection<Document> collection = database.getCollection("testcollection"); collection.deleteOne(Filters.eq("name", "John")); System.out.println("Document deleted successfully"); } } ``` ### 实验注意事项 - 确保 MongoDB 服务器已启动,并且监听的端口正确。 - 在进行数据库操作时,要处理可能出现的异常,如网络异常、数据库连接异常等。 - 对于 MongoDB 的权限管理,要合理设置用户权限,避免数据泄露。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值