MongoDB:索引、条件更新与关注级别实验
基线 MongoDB Server 7.0.14,WiredTiger 使用该 Server tag 所带版本,源码说明见MongoDB 正文。模型与真服务实验分开输出,不能把单节点命令当作多副本故障证据。
下载完整输入
仓库内从根目录运行。单独下载请将六份文件保存在同一目录,使用 bash run.sh --model / bash run.sh --service;脚本依据自身位置读取相邻依赖。
- run.sh:Bash 公开入口。
- fixture.json:数组 cross/same、库存 100 扣 80、重复请求键、事务错误标签、历史窗口及 10000 订单配置。
- model.py:Python 3.9+ 标准库有限模型,不访问数据库。
- run_service.py:Python 只读 TCP 预检,调用 PATH 中的
mongosh,生成独有数据库名。 - verify.js:mongosh 实际命令与断言,不依赖 npm 包。
- compose.yaml:可选 7.0.14 单节点复制集,绑定
127.0.0.1:17017。
有限模型:谓词与结果未知
服务模式默认严格要求 7.0.14 可写复制集。其他 MongoDB 7.x 可以用 --server-version 显式指定精确运行版本,源码基线不变。已有 standalone 可显式传 --standalone,仅执行索引、查询、唯一键、单文档 CAS 与 local/w1/j 断言;输出 scope: standalone subset 和未运行列表,不声称通过复制集实验。
bash labs/data-senior/mongodb/run.sh --model数组 cross 的 A/1 与 B/5 分别满足两个点路径条件,same 的 A/5 满足同元素条件:宽松查询返回 cross/same,$elemMatch 仅 same。两个调用者都拿 version=1,写入点重检后 matchedCount 为 [1,0],库存 20、版本 2;相同 tenant/request_id 第二次插入为 duplicate-key。
超时模型选择“已执行、确认丢失”这一反例:客户端 UNKNOWN 而存储中仍为 20,说明超时不构成回滚证明;它不推断每次超时都已执行。TransientTransactionError、UnknownTransactionCommitResult、无标签分别引导重试事务体、重试提交、核查原因。token=20 在 [15,40] 窗口内,token=12 不可续。入口为这些手算真值提供断言,失败非零;时间窗口只是简化的整数模型,真实 resume token 为不透明值,不能自行比较解析。
该模型没有运行 BSON 比较、KeyString、WT 并发冲突、journal、oplog、驱动重试或复制协议。
已有复制集的真实命令
需要 Python、PATH 中的 mongosh 和一个已初始化且可写的 7.0.14 replica set。入口只读检查版本/hello,不执行 rs.initiate、改配置或启动服务。默认:
bash labs/data-senior/mongodb/run.sh --service
# 仅在独立实验复制集位于27017时显式指定:
bash labs/data-senior/mongodb/run.sh --service --uri 'mongodb://127.0.0.1:27017/?directConnection=true'步骤和字面断言:
- 新建
study_t18_mongo_<UUID>数据库和 ownership 标记;写前拒绝已存在非空 namespace。10000 订单分 10 租户,索引{tenant:1,createdAt:-1,total:1}。相同 tenant=3 的覆盖投影返回 1000、docsExamined=0;包含 payload 后返回 1000、docsExamined=1000,报告保存实际 winningPlan(可能 classic/SBE)与 executionStats。 - 唯一索引
{tenant:1,request_id:1}的第二次插入必须报 11000,不能把任意异常当成功。数组点路径命中 2,$elemMatch命中 1。库存两次同谓词更新为[1,0],最终 stock=20/version=2。 - 显式 primary 路由下对照 local read + w:1/j、majority read + majority/j,以及同一因果 session 的 majority 读写;每次都检查 writeErrors/writeConcernError。这验证参数被接受与该单节点结果,不证明任意 secondary 已应用或跨机房因果延迟。
- snapshot 事务将两个账户从 100/0 改为 90/10;change stream 接收一个 insert 和服务器 resume token。没有制造提交响应丢失、错误标签、rollback 或窗口过期,相关失败只在有限模型与源码/纸面推演中讨论。
finally 关闭 stream/session,核对自己的 ownership 标记后只 drop 自己生成的数据库,并核对集合清空;不固定或清空 study 库,不扫描/删除其他库。首个写是 ownership 插入,创建响应丢失也会在 finally 定向检查标记;非空却无标记时拒绝删除并报告清理失败。强杀进程或清理时断网仍可能留下 UUID namespace。JSON 给出 namespace、完成断言与清理结果。
可选 Compose 与当前实际范围
学习者可自行选择 compose.yaml 建独立单节点。要求可用 Docker daemon/镜像;每次使用独立项目名,只在这个实验容器里初始化 study-rs:
mongo_project="t18-mongo-$(python3 -c 'import uuid; print(uuid.uuid4().hex[:12])')"
docker compose -p "$mongo_project" -f labs/data-senior/mongodb/compose.yaml up -d
docker compose -p "$mongo_project" -f labs/data-senior/mongodb/compose.yaml exec mongo mongosh --quiet --eval 'rs.initiate({_id:"study-rs",members:[{_id:0,host:"mongo:27017"}]})'
# 等待hello.isWritablePrimary为true;宿主机装有mongosh后运行 --service。
docker compose -p "$mongo_project" -f labs/data-senior/mongodb/compose.yaml down2026-10-23 实际结果:有限模型/公开命令测试通过;服务入口 TCP 17017 为 Connection refused,未创建数据库;27017 只读端口探测也拒绝,PATH 未发现 mongosh。Docker CLI 29.8.2 存在,但 OrbStack daemon socket 不存在。本轮未安装、拉镜像、启动服务或改用户配置;verify.js 仅做 JS 语法检查,全部数据库断言待环境验证。
单节点 majority 只涉及自身,不能证明多副本容错、secondary 落后、真实 wtimeout、回滚、切主/分区、恢复备份、oplog 过期或分片唯一性。本实验对这些结论不输出伪造 PASS。
T37 本机服务复核(2026-10-24)
bash labs/data-senior/mongodb/run.sh --service --uri 'mongodb://127.0.0.1:27017/?directConnection=true' --server-version 7.0.45 --standalone本机已有 MongoDB 7.0.45 standalone;mongosh 客户端安装在本轮临时目录,未改服务配置。首次实跑发现旧 shell 的 assert.eq 不适用于 mongosh,已改为 Node 严格断言,避免把语法检查当成实验通过。真实运行得到:10000 订单覆盖查询 docsExamined=0、取 payload=1000;唯一键重复错误 11000;数组宽松匹配 2、elemMatch=1;两次 CAS 匹配 [1,0],库存20/版本2;local 读与 w1/j 写通过。自己的 UUID 数据库已按 ownership 标记清理并核对为空。
--standalone 明确跳过 majority/因果 session 对照、snapshot 多文档事务和 change stream/resume token;没有将用户服务改为复制集。默认 7.0.14 预检在该服务器上拒绝且不创建数据库,显式 7.0.45 的完整复制集入口也拒绝 standalone。复制集、切主、窗口过期与恢复故障仍未实跑。