mongodb - 如何减少获取 mongodb 模式锁所花费的时间?
问题描述
我们在生产中有一个由 WiredTiger 支持的 mongodb 集群,其中包含一个由一个主节点和两个从节点组成的 3 节点副本集。其中一个从站有另一个服务,该服务位于同一位置,广泛地查询从站。在解决托管服务中的一些缓慢问题时,我看到了很多令人惊讶的缓慢查询。这个耗时 3.3 秒:
find: "myColl",
filter: { myField: "myValue" },
projection: { name: 1 },
$db: "myDb",
$clusterTime: { clusterTime: Timestamp(1568198047, 3), signature: { hash: BinData(0, 0000000000000000000000000000000000000000), keyId: 0 } },
lsid: { id: UUID("2ed823aa-e6af-4898-a4c1-c039d28a32ab") },
$readPreference: { mode: "secondary" } }
planSummary: IXSCAN { myField: 1 } keysExamined:0 docsExamined:0 cursorExhausted:1 numYields:0 nreturned:0 reslen:232
locks:{ Global: { acquireCount: { r: 1 } },
Database: { acquireCount: { r: 1 } },
Collection: { acquireCount: { r: 1 } } }
storage:{ data: { bytesRead: 355, timeReadingMicros: 4 }, timeWaitingMicros: { schemaLock: 3284692 }
对我来说最突出的一行是最后一行,表明它花费了 99.9% 的时间来等待获取称为模式锁的东西。
我检查了这个特定的数据库和集合,结果发现该集合在查询时有 50 个项目。此外,还有一个关于myField
.
为什么读取查询等待获取模式锁?我能做些什么来消除这个漫长的等待?
解决方案
不久前我一直在研究这个主题,就我而言,我无法在 MongoDB 上进行太多调整,所有索引都在那里,并且我优化了查询数据库的方式。
我调试的方式是首先获取所有数据库统计信息,以便清楚地了解锁和并发:
> db.serverStatus().globalLock
{
"totalTime" : <num>,
"currentQueue" : {
"total" : <num>,
"readers" : <num>,
"writers" : <num>
},
"activeClients" : {
"total" : <num>,
"readers" : <num>,
"writers" : <num>
}
}
> db.serverStatus().locks
{
<type> : {
"acquireCount" : {
<mode> : NumberLong(<num>),
...
},
"acquireWaitCount" : {
<mode> : NumberLong(<num>),
...
},
"timeAcquiringMicros" : {
<mode> : NumberLong(<num>),
...
},
"deadlockCount" : {
<mode> : NumberLong(<num>),
...
}
}
如果你有 studio3t,那么分析统计数据并获得一些可视化会更容易。
如果您的系统尚未使用wiredTiger,您可以考虑:https ://docs.mongodb.com/manual/core/wiredtiger/
WiredTiger 使用文档级并发控制进行写入操作。因此,多个客户端可以同时修改一个集合的不同文档。对于大多数读写操作,WiredTiger 使用乐观并发控制。WiredTiger 仅在全局、数据库和集合级别使用意图锁。当存储引擎检测到两个操作之间的冲突时,会引发写入冲突,导致 MongoDB 透明地重试该操作。
在我们的例子中,我们在一些不需要如此快速响应的请求中增加了一些批量大小,并删除了一些在我们的例子中对 inser 有影响的索引。
推荐阅读
- ruby-on-rails - Rails 应用程序支持不同的时区
- node.js - Firebase 部署在控制台中有效,但在 bitbucket 管道中无效
- python - Pandas,为什么字符串匹配在第一个字母处停止
- css - 如何删除 Wordpress 中标题和滑块之间的空白?
- ios - 我无法在 Xcode 12 的 xib 中创建自定义 UIView
- c# - 如何从 WPF DataGrid 获取单元格内容
- angular - 在primeng中,我们如何获取表格列的默认下拉值过滤器
- spring - Spring中viewResolver的多个后缀?
- php - 如何从数字中获取 PHP 中一个月中的特定日期?
- angular - angular-cli 未更新,ng serve 不起作用