MongoDB CRUD操作:快照查询

MongoDB CRUD操作:快照查询

文章目录

  • MongoDB CRUD操作:快照查询
    • 对比本地和快照的读关注
    • 举例
      • 从相同的时间点运行查询
      • 从过去某个时刻读取数据的一致状态
    • 配置快照保留时间
      • 磁盘空间和历史记录

使用快照查询可以读取最近某个时间点的数据,而且从MongoDB 5.0开始,可以使用读关注"snapshot"来查询二级节点上的数据,这显著提高了应用程序读取的通用性和弹性,而且无需像以前那样,先创建数据的静态副本,将其转移到一个单独的系统中,然后手动隔离这些长期运行的查询,以免干扰正常运行工作负载。相反,可以在从一致的数据状态读取数据的同时,针对实时事务数据库执行长期运行查询。

在辅助节点上使用读关注"snapshot"不会影响应用程序的写工作量,只有应用程序读取才会从隔离到辅助节点的长期运行查询中受益。

下面的情况建议使用快照查询:

  • 执行多个相关查询,并确保每个查询从同一时间点读取数据。
  • 确保从过去某个时间点的一致数据状态读取数据。

对比本地和快照的读关注

当使用MongoDB默认的本地读取关注执行长时间运行的查询时,查询结果可能包含与查询同时发生的写入数据,因此,查询可能会返回意外或不一致的结果。

为了避免这种情况,可以创建一个会话并指定读关注"snapshot",通过读取关注"snapshot",MongoDB可以通过快照隔离运行查询,这意味着查询只读取最近单个时间点出现的数据。

举例

从相同的时间点运行查询

读关注"snapshot"允许在会话中运行多个相关查询,并确保每个查询从相同的时间点读取数据。

例如,动物收容所有一个宠物数据库,其中包含每种宠物的集合。宠物数据库有catsdogs两个集合,它们都包含一个adoptable字段,表示宠物是否可以领养。其中,cats集合中的文档如下所示:

{"name": "Whiskers","color": "white","age": 10,"adoptable": true
}

如果要查询所有集合中可供收养的宠物总数,为了提供一致的数据视图,需要返回两个集合同一时间点的数据。这时,就可以在会话中使用读关注快照:

mongoc_client_session_t *cs = NULL;
mongoc_collection_t *cats_collection = NULL;
mongoc_collection_t *dogs_collection = NULL;
int64_t adoptable_pets_count = 0;
bson_error_t error;
mongoc_session_opt_t *session_opts;cats_collection = mongoc_client_get_collection (client, "pets", "cats");
dogs_collection = mongoc_client_get_collection (client, "pets", "dogs");/* 使用 pets.cats 和 pets.dogs 数据作为示例 */
if (!pet_setup (cats_collection, dogs_collection)) {goto cleanup;
}/* 启动会话快照 */
session_opts = mongoc_session_opts_new ();
mongoc_session_opts_set_snapshot (session_opts, true);
cs = mongoc_client_start_session (client, session_opts, &error);
mongoc_session_opts_destroy (session_opts);
if (!cs) {MONGOC_ERROR ("Could not start session: %s", error.message);goto cleanup;
}/** 执行下面的聚合管道,将合计值累加到adoptable_pets_count。**  adoptablePetsCount = db.cats.aggregate(*      [ { "$match": { "adoptable": true } },*        { "$count": "adoptableCatsCount" } ], session=s*  ).next()["adoptableCatsCount"]**  adoptablePetsCount += db.dogs.aggregate(*      [ { "$match": { "adoptable": True} },*        { "$count": "adoptableDogsCount" } ], session=s*  ).next()["adoptableDogsCount"]** 注意,要实现这个操作必须要通过mongoc_collection_aggregate把客户端会话传递给选项,即:** mongoc_client_session_append (cs, &opts, &error);* cursor = mongoc_collection_aggregate (*    collection, MONGOC_QUERY_NONE, pipeline, &opts, NULL);*/
accumulate_adoptable_count (cs, cats_collection, &adoptable_pets_count);
accumulate_adoptable_count (cs, dogs_collection, &adoptable_pets_count);printf ("there are %" PRId64 " adoptable pets\n", adoptable_pets_count);

在上面的一系列操作中:

  • 使用MongoClient()与MongoDB实例建立连接。
  • 切换到pets数据库。
  • 建立会话,该命令指定了snapshot=True,因此会话使用读关注快照。
  • pets数据库中的每个集合执行下列操作:
    • 使用$match过滤adoptable字段为True的文件。
    • 使用$count返回已筛选文档的计数。
    • 用数据库中的计数递增adoptablePetsCount变量。
  • 打印adoptablePetsCount变量。

会话中的所有查询都会读取同一时间点出现的数据,因此,最终计数反映的是一致的数据快照。

注意:如果会话持续时间超过WiredTiger历史记录保留期(默认为 300 秒),查询就会出现快照过旧(SnapshotTooOld)错误。

从过去某个时刻读取数据的一致状态

读关注快照可确保查询能读取最近某个时间点出现的数据。例如:一家在线鞋店有一个sales集合,其中包含该店售出的每一件商品的数据。其中,sales集合中的一个文档如下所示:

{"shoeType": "boot","price": 30,"saleDate": ISODate("2022-02-02T06:01:17.171Z")
}

每天晚上都会运行一个查询来查看当天售出了多少双鞋。每日销售查询如下所示:

mongoc_client_session_t *cs = NULL;
mongoc_collection_t *sales_collection = NULL;
bson_error_t error;
mongoc_session_opt_t *session_opts;
bson_t *pipeline = NULL;
bson_t opts = BSON_INITIALIZER;
mongoc_cursor_t *cursor = NULL;
const bson_t *doc = NULL;
bool ok = true;
bson_iter_t iter;
int64_t total_sales = 0;sales_collection = mongoc_client_get_collection (client, "retail", "sales");/* 使用'retail.sales'示例数据 */
if (!retail_setup (sales_collection)) {goto cleanup;
}/* 开始快照会话 */
session_opts = mongoc_session_opts_new ();
mongoc_session_opts_set_snapshot (session_opts, true);
cs = mongoc_client_start_session (client, session_opts, &error);
mongoc_session_opts_destroy (session_opts);
if (!cs) {MONGOC_ERROR ("Could not start session: %s", error.message);goto cleanup;
}if (!mongoc_client_session_append (cs, &opts, &error)) {MONGOC_ERROR ("could not apply session options: %s", error.message);goto cleanup;
}pipeline = BCON_NEW ("pipeline","[","{","$match","{","$expr","{","$gt","[","$saleDate","{","$dateSubtract","{","startDate","$$NOW","unit",BCON_UTF8 ("day"),"amount",BCON_INT64 (1),"}","}","]","}","}","}","{","$count",BCON_UTF8 ("totalDailySales"),"}","]");cursor = mongoc_collection_aggregate (sales_collection, MONGOC_QUERY_NONE, pipeline, &opts, NULL);
bson_destroy (&opts);ok = mongoc_cursor_next (cursor, &doc);if (mongoc_cursor_error (cursor, &error)) {MONGOC_ERROR ("could not get totalDailySales: %s", error.message);goto cleanup;
}if (!ok) {MONGOC_ERROR ("%s", "cursor has no results");goto cleanup;
}ok = bson_iter_init_find (&iter, doc, "totalDailySales");
if (ok) {total_sales = bson_iter_as_int64 (&iter);
} else {MONGOC_ERROR ("%s", "missing key: 'totalDailySales'");goto cleanup;
}

在上面的一系列操作中:

  • 使用$match$exprsaleDate字段进行过滤。
    • $expr允许在$match阶段使用聚合表达式(如 NOW)。
  • 使用$gt运算符和$dateSubtract表达式,返回saleDate大于执行查询前一天的文档。
  • 使用 $count 返回匹配文档的计数。计数存储在 totalDailySales 变量中。
  • 指定读关注快照,确保查询从单一时间点读取。

因为sales集合比较大,所以运行查询可能需要几分钟时间。由于是在线商店,销售可能在一天中的任何时间发生。

例如下面的情况:

  • 查询在上午 12:00 开始执行。
  • 一位顾客在上午 12:02 时购买了三双鞋。
  • 查询在凌晨 12:04 执行完毕。

如果查询不使用读关注快照,那么在查询开始和查询结束之间发生的销售额就会包含在查询计数中,尽管这些销售额并不是在报告当天发生的。这可能导致报告不准确,某些销售额被计算两次。

指定读取 "快照 "后,查询只返回查询开始执行前不久数据库中的数据。

如果查询时间超过WiredTiger历史保留期(默认情况下为 300 秒),查询就会出错,并显示 SnapshotTooOld 错误。

配置快照保留时间

默认情况下,WiredTiger 存储引擎会保留 300 秒的历史记录。使用 snapshot=true 的会话,从会话中的第一个操作开始到最后一个操作结束,总共可使用 300 秒。如果使用会话的时间更长,会话就会因 SnapshotTooOld 错误而失败。同样,如果使用读关注快照来查询数据,且查询持续时间超过 300 秒,查询就会失败。

如果查询或会话运行时间超过 300 秒,可以考虑延长快照保留时间,可以通过修改minSnapshotHistoryWindowInSeconds参数增加快照保留期,例如,把minSnapshotHistoryWindowInSeconds 的值设置为 600 秒:

db.adminCommand( { setParameter: 1, minSnapshotHistoryWindowInSeconds: 600 } )

磁盘空间和历史记录

需要注意,增加 minSnapshotHistoryWindowInSeconds 的值会增加磁盘使用量,因为服务器必须在指定的时间窗口内保持较早修改值的历史记录。磁盘空间的使用量取决于工作负载,工作量越大,需要的磁盘空间就越大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/19088.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于51单片机的温控风扇的设计–仿真设计

可实现通过DS18B20测量当前环境温度 可实现通过温度自动控制风扇转速 可实现通过按键设置不同风速对应的温度 可实现通过按键切换自动、手动模式 可实现在手动模式下通过按键调整风扇转速 可实现通过LCD1602显示温度、风扇转速挡位、自动/手动模式

【C++】模拟实现string类

🦄个人主页:修修修也 🎏所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 一.了解项目功能 二.逐步实现项目功能模块及其逻辑详解 🎏构建成员变量 🎏实现string类默认成员函数 📌构造函数 📌析构函数…

k8s 全面掌控日志系统

概述 为了提高系统运维和故障排查的效率, 日志系统采用 ELK(Elasticsearch、Logstash、Kibana)技术栈,通过 FileBeats 作为日志收集器,将来自不同节点的日志数据汇总并存储在 Elasticsearch 中,最终通过 K…

创建一个新的Spring Security应用程序,并使用JDBC连接数据库

创建一个新的Spring Security应用程序,并使用JDBC连接数据库 在这个教程中,我们将学习如何创建一个新的Spring Security应用程序,使用JDBC连接数据库以获取用户信息并进行认证。我们还将学习如何配置Spring Security以从数据库中获取用户和权…

Vue3使用Composition API实现响应式

title: Vue3使用Composition API实现响应式 date: 2024/5/29 下午8:10:24 updated: 2024/5/29 下午8:10:24 categories: 前端开发 tags: Vue3CompositionRefsReactiveWatchLifecycleDebugging 1. 介绍 Composition API是Vue.js 3中新增的一组API,用于在组件中组…

SQL 语言:嵌入式 SQL 和动态 SQL

文章目录 基本概述嵌入式 SQL动态 SQL总结 基本概述 嵌入式SQL和动态SQL是两种在应用程序中嵌入和使用SQL语句的方法。它们都允许开发人员在编程语言中编写SQL语句,以便在应用程序中执行数据库操作。然而,这两种方法在实现方式、性能和灵活性方面存在一…

Java数据结构与算法(红黑树)

前言 红黑树是一种自平衡二叉搜索树,确保在插入和删除操作后,树的高度保持平衡,从而保证基本操作(插入、删除、查找)的时间复杂度为O(log n)。 实现原理 红黑树具有以下性质: 每个节点要么是红色&#…

go语言学习之旅之Go结构体

在Go语言中,结构体(struct)是一种用户定义的数据类型,用于组合不同类型的数据项。结构体可以包含其他结构体或基本数据类型的字段。以下是关于Go语言结构体的基本知识: 定义结构体: package mainimport &…

Python 之微信指数小程序数据抓取

Fiddler安装和设置 安装 Fiddler 安装包可以从这里获取,如果失效了可以自己网上找一个安装。 链接:https://pan.baidu.com/s/1N30BoDWm2_dBL8i8GRzK5g?pwd1znv 提取码:1znv 然后就是点击安装就好了,没什么好多说的。 启用…

刷代码随想录有感(83):贪心算法——最大子数组和

题干&#xff1a; 代码&#xff1a; class Solution { public:int maxSubArray(vector<int>& nums) {int res INT_MIN;int count 0;for(int i 0; i < nums.size(); i){count nums[i];if(count > res) res count;if(count < 0)count 0;}return res;} …

【创作活动】探索 GPT-4o:下一代语言模型的技术革命

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

HTTP报文

HTTP报文 报文流 HTTP报文是在HTTP引用程序之间发送的数据块&#xff0c;这些数据块以一种文本形式的元信息开头&#xff0c;这些信息描述了报文的内容和含义&#xff0c;后面跟着可选的数据部分&#xff0c;这些报文在客户端&#xff0c;服务器和代理之间流动。 报文流入源…

git更改本地项目关联到新仓库

删除现在远程关联的仓库 git remote rm origin链接新仓库 git remote add origin url(需要关联的新仓库地址)代码提交到远程仓库master分支 git push --set-upstream origin master本地分支更新同步至远程仓库 比如本地有dev分支 git push origin dev:dev

前端项目开发,3个HTTP请求工具

这一小节&#xff0c;我们介绍一下前端项目开发中&#xff0c;HTTP请求会用到的3个工具&#xff0c;分别是fetch、axios和js-tool-big-box中的jsonp请求。那么他们都有哪些小区别呢&#xff1f;我们一起来看一下。 目录 1 fetch 2 axios 3 js-tool-big-box 的 jsonp 请求 …

拷贝构造、移动构造、拷贝赋值、移动赋值

最近在学习C的拷贝构造函数时发现一个问题&#xff1a;在函数中返回局部的类对象时&#xff0c;并没有调用拷贝构造函数。针对这个问题&#xff0c;查阅了一些资料&#xff0c;这里记录整理一下。 调用拷贝构造函数的三种情况&#xff1a; ① 用一个类去初始化另一个对象时&a…

【数据结构与算法 | 基础篇 | 队列篇】力扣102, 107

1. 力扣102 : 二叉树的层序遍历 (1). 题 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3]…

对于高速信号完整性,一块聊聊啊(18)

本文摘录一篇Allegro进行后仿真的完整流程,可能allegro版本有点老,但整个过程还是描述比较详细的。 目录 1、获取IBIS模型 1.1模型下载 1.2检查IBIS模型 1.3IBIS转换为DML 1.4保存DML模型 2、仿真准备 2.1叠层设置 2.2电源网格设置 2.3仿真库配置 3、仿真 3.1拓扑…

刷爆leetcode第六期

题目一 用队列实现栈 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入栈顶。 int pop() 移除…

【漏洞复现】大华智能物联综合管理平台 fastjson远程代码执行漏洞

0x01 产品简介 大华ICC智能物联综合管理平台对技术组件进行模块化和松耦合&#xff0c;将解决方案分层分级&#xff0c;提高面向智慧物联的数据接入与生态合作能力。 0x02 漏洞概述 由于大华智能物联综合管理平台使用了存在漏洞的Fastson组件,未经身份验让的攻击者可利用 /e…

M功能-支付平台(六)

target&#xff1a;离开柬埔寨倒计时-217day 今天突然发现我在csdn居然把我ip属地搞出来了&#xff0c;之前都没注意到&#xff0c;哎 前言 M功能演示版本做到后期(也就是第二周的后面3天)真的很心酸&#xff0c;这边安排的4后端后面都放弃了&#xff0c;觉得做不出来&#…