长事务本身不慢,但会因锁竞争、内存膨胀、网络等待三者叠加拖垮吞吐量;快照占用内存随修改文档数与大小线性增长,易触发 page eviction;collscan 导致集合级锁争用;跨节点 2pc 受网络延迟影响显著;需日常监控 currentactive、totaldocsexamined 和 p99 rtt。

长事务本身不慢,但会放大底层问题——锁竞争、内存膨胀、网络等待三者叠加,直接拖垮吞吐量。
事务快照吃光 WiredTiger 缓存
WiredTiger 在事务生命周期内必须保留所有被修改文档的原始版本(快照),内存占用随修改文档数 × 文档大小线性增长。一个修改 5000 条、平均 2MB 的日志文档的事务,仅快照就占掉 10GB 内存。
-
wiredTigerCacheSizeGB配置过小(如默认 1GB)时,快照挤占缓存空间,触发频繁 page eviction,磁盘 IO 暴增 - 事务未提交前,快照无法释放;超时或崩溃后,回滚阶段仍需遍历快照,CPU 和内存压力持续
- 用
db.runCommand({serverStatus: 1}).metrics.transaction查currentActive和currentInactive,若前者长期 > 3 且后者不降,说明快照在堆积
COLLSCAN 在事务里变成集合级锁争用
事务内查询没走索引,WiredTiger 会从文档级锁退化为集合级锁——不是“锁慢”,是“锁住别人”。多个事务同时全表扫,排队等锁,totalDocsExamined 远大于 nReturned 就是信号。
- 执行
db.collection.explain("executionStats").find({…}),重点看executionStages.stage是否为COLLSCAN - 比值
totalDocsExamined / nReturned > 10时,该查询不该放进事务 - 避免在事务中用
$where、无前缀正则(如/abc$/)、$text等无法走 B-tree 索引的操作
跨节点协调被网络延迟卡死
事务依赖两阶段提交(2PC),prepare/commit 阶段需 mongos、shard、config server 多轮 RPC。RTT 超 10ms,P99 延迟就可能飙升到百毫秒级,失败率陡增。
- 分片集群下,事务必须含分片键,否则升级为全局锁协调,延迟翻倍
- 连接字符串里写域名而非内网 IP,DNS 解析可能拖慢 prepare 阶段
- 用
db.runCommand({ping: 1})测真实协议层 RTT,连续跑 100 次看 P99 是否稳定在 3ms 内
真正危险的不是“事务大”,而是“快照看不见、锁排不上、网络卡不住”——这三个问题往往同时发生,且监控指标滞后于实际恶化。别等 OOM 或超时才查,日常就得盯 currentActive、totalDocsExamined 和 P99 RTT。











