目录
四、验证与修复
1. 修复服务器
2. 验证单个集合
3. 修复集合验证错误
4. 压缩集合的数据文件
五、监控
1. 查看服务器状态
2. 查看命令行参数
3. 查看数据库/表状态
4. 查看当前Query执行情况
5. 监控MongoDB状态
六、其它常见任务
1. 启动服务器
2. 获取服务器版本
3. 关闭服务器
4. 轮换日志文件
5. 刷写并锁
6. 升级MongoDB
四、验证与修复
以下是一些数据已损坏的迹象:
- 数据库服务器无法启动,表示数据文件已损坏。
- 在服务器日志文件中发现asserts或使用db.serverStatus()命令时发现asserts数目很大。
- 查询结果很奇怪或出乎意料。
- 集合中的记录数与预期不匹配。
任何一种迹象都可能表示应用出现了问题,或更麻烦的是,数据损坏或处于不一致状态。
1. 修复服务器
mongod --dbpath /data/db --repair
注意使用repair命令是一个代价很高的操作,它将花费很长时间,并要求使用两倍于MongoDB数据文件大小的空间,因为所有的数据都将被克隆到新的文件并重建,这本质上是对所有数据文件的重建。
一旦修复结束,就可以正常启动服务器,然后从备份中恢复任何丢失的数据。如果尝试修复一个大型数据库,那么驱动器上的磁盘空间可能会不足,因为MongoDB需要在同一驱动器上创建数据库的副本作为数据源。为了处理这个问题,MongoDB修复工具提供了一个额外的命令行参数--repairPath。可以使用该参数指定一个具有足够空间的驱动器用于保存修复过程中创建的临时文件:
mongod -f /etc/mongodb.conf --repair --repairpath /mnt/bigdrive/tempdir
2. 验证单个集合
> use test
switched to db test
> db.products.validate();
{
"ns" : "test.products",
"nInvalidDocuments" : NumberLong(0),
"nrecords" : 3,
"nIndexes" : 1,
"keysPerIndex" : {
"test.products.$_id_" : 3
},
"valid" : true,
"warnings" : [
"Some checks omitted for speed. use {full:true} option to do more thorough scan."
],
"errors" : [ ],
"ok" : 1
}
>
默认情况下,validate选项将同时检查数据文件和索引,并在操作完成之时提供集合的一些统计信息。该选项将显示数据文件或索引中是否存在问题,但不会检查所有文档的正确性。如果希望检查所有文档,可以在函数调用时添加true参数即可:
> db.products.validate(true);
{
"ns" : "test.products",
"nInvalidDocuments" : NumberLong(0),
"nrecords" : 3,
"nIndexes" : 1,
"keysPerIndex" : {
"test.products.$_id_" : 3
},
"indexDetails" : {
"test.products.$_id_" : {
"valid" : true
}
},
"valid" : true,
"warnings" : [ ],
"errors" : [ ],
"ok" : 1
}
>
也可以使用validate选项只验证索引:
> db.runCommand({validate:"products", scandata:false});
{
"ns" : "test.products",
"nInvalidDocuments" : NumberLong(0),
"nrecords" : 3,
"nIndexes" : 1,
"keysPerIndex" : {
"test.products.$_id_" : 3
},
"valid" : true,
"warnings" : [
"Some checks omitted for speed. use {full:true} option to do more thorough scan."
],
"errors" : [ ],
"ok" : 1
}
>
3. 修复集合验证错误
如果在验证集合的过程中出现错误(显示在验证文档的errors部分),有几种方式可以修复数据(注意一定要对备份数据)。在恢复备份之前,应该先查看MongoDB实例的日志,检查是否存在任何关于该错误的相关信息;如果有,则该信息将提示下一个需要完成的步骤。
(1)修复索引
如果验证结果显示索引是损坏的,那么可以重建受影响集合的索引:
> db.products.reIndex();
{
"nIndexesWas" : 1,
"nIndexes" : 1,
"indexes" : [
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.products"
}
],
"ok" : 1
}
>
MongoDB将会删除集合中目前的所有索引,然后重建它们。如果使用了数据库的repair选项,也将在数据库的所有集合中运行reIndex()函数。
(2)修复数据文件
修复所有数据文件的最好也是最危险的方式是:使用服务器的--repair选项或db.repairDatabase()命令。后者将修复单个数据库中的所有集合文件,然后重建所有已定义的索引。
> use test;
switched to db test
> db.repairDatabase();
{ "ok" : 1 }
>
repairDatabase()不适合在在线服务器上运行,因为它在重建数据文件时会阻塞对数据的所有请求。这将导致数据库修复过程中的所有读写操作都被阻塞。
MongoDB的修复功能是一个强力选项。它尝试修复并重建数据结构和索引,这通过从磁盘读取并重建整个数据结构的方式来完成。如果可能,应该尝试从备份文件恢复;repairDatabase()只应被用作最后的解决方案。
4. 压缩集合的数据文件
> use test;
switched to db test
> db.runCommand({compact:"products"});
{ "ok" : 1 }
>
命令compact会在已有数据文件中为指定的集合整理并重组数据结构,使用默认的WiredTiger存储引擎会恢复磁盘空间,但对于老的MMAPv1存储引擎,不会释放磁盘空间。
五、监控
1. 查看服务器状态
db.serverStatus();
输出中可以看到MongoDB的版本、后台刷写情况、副本集情况、操作数量情况、进出网络情况、连接数情况和内存情况等信息。其中内存相关字段的含义是(单位是M):
- mapped:映射到内存的数据大小
- visze:占用的虚拟内存大小
- res:实际使用的内存大小
serverStatus输出了很多细节,在该函数的输出信息中可以找到两个最重要的部分:opcounters和asserts。
opcounters部分显示了数据库服务器上已经执行的每种操作的数目。对于特定应用,应该知道这些计数器的正常情况。如果这些计数器开始偏离正常的比例,那么可能就是早期的警告:应用中出现了问题。
asserts部分展示了服务器和客户端抛出异常或警告的数目。如果异常或警告的数目迅速增加,那么最好查看服务器的日志文件,以检查是否系统出现了问题。大量的断言也可能表示数据库中出现了问题,应该检查MongoDB实例的日志文件,以确认这些断言是否属于普通的用户断言,如重复键值冲突等等问题。
也可以通过mongostat来查看:
mongostat -u wxy --authenticationDatabase admin
mongostat提供MongoDB服务器当前状态的概览,例如,将显示出数据库操作的执行频率、索引的命中率以及应用等待数据库释放锁所耗费的时间。最有用的主要数据列是前6列,它们将显示出mongod服务器处理特定操作的速率。在分析问题时,值得关注的其它列还有:
- faults:查询从磁盘读取数据,标志服务器未达到最佳,所需的数据并未完全保存找内存中。
- qr/qw:队列等待的数目。因为MongoDB支持一个写入器(插入、更新和删除)和多个读取器(查找),这可能导致出现读取查询被表现不佳的写操作阻塞的情况。更糟糕的是,可能出现许多读/写操作同时被一个性能不佳的写操作阻塞的情况。检查是否存在某个查询阻塞了其它查询的执行。
- ar/aw:活动客户端的数目。
- conn:打开的连接数。
- flushes:数据刷写到磁盘的数目。
- vsize:使用虚拟内存大小。
- mapped:隐射的内存大小,约等于数据目录大小。
2. 查看命令行参数
> db.serverCmdLineOpts();
{
"argv" : [
"mongod",
"-f",
"/home/mongodb/mongodb-4.0.2/mongodb.conf"
],
"parsed" : {
"config" : "/home/mongodb/mongodb-4.0.2/mongodb.conf",
"net" : {
"bindIpAll" : true
},
"processManagement" : {
"pidFilePath" : "/home/mongodb/mongodb-4.0.2/data/mongodb.pid"
},
"security" : {
"authorization" : "enabled"
},
"storage" : {
"dbPath" : "/home/mongodb/mongodb-4.0.2/data/"
},
"systemLog" : {
"destination" : "file",
"path" : "/home/mongodb/mongodb-4.0.2/data/mongodb.log"
}
},
"ok" : 1
}
>
3. 查看数据库/表状态
db.stats(1024*1024);
返回数据库的名称,集合数量,索引数量、大小,数据文件大小,存储空间大小和物理文件大小,以MB为单位。
db.collection.stats(1024*1024);
4. 查看当前Query执行情况
db.currentOP();
查看当前执行的进程,类似MySQL的show processlist。可以添加过滤条件:
db.currentOP({"ns":"test"});
5. 监控MongoDB状态
mongotop -u wxy --authenticationDatabase admin
查看哪些对象最繁忙。
mongostat -u wxy --authenticationDatabase admin
insert、query、update、delete、getmore、command表示每种对应操作的发生次数。其中faults表示访问失败数,数据从内存交换出去,放到swap。值越小越好,最好不要大于100。
- flushes:表示刷写到磁盘的次数。
- mapped:表示映射到内存的数量,约等于数据目录大小。
- vsize:表示正在使用的虚拟内存大小,通常为数据目录的2倍。(一次用于映射,一次用于日志系统)
- res:表示正在使用的内存大小。
- qr|qw:表示读写操作队列大小,即有多少读写操作被阻塞,等待进行处理。
- ar|aw:表示活动客户端的数量,即正在进行读写操作的客户端。
- netId:表示通过网络传输进来的字节数。
- netou:t表示通过网络传输出的字节数。
- Conn:表示服务器打开的连接数。
- time:表示统计的时间。
六、其它常见任务
1. 启动服务器
mongod -f /home/mongodb/mongodb-4.0.2/mongodb.conf &
2. 获取服务器版本
use admin;
db.version();
3. 关闭服务器
use admin
db.shutdownServer()
当且仅当服务器不响应上面方法时,使用下面的命令停止服务器:
sudo killall -15 mongod
4. 轮换日志文件
use admin;
db.adminCommand({"logRotate":1});
这个命令类似与MySQL的flush log,它告诉MongoDB开始编写一个新的日志文件,用转换它时的时间戳重命名现有文件。之后这些旧文件可以安全的删除。还可以指导MongoDB转换日志,不需要使用如下的SIGUSR1信号连接实例:
kill -SIGUSR1 `pidof mongod`
5. 刷写并锁
> db.fsyncLock() # 刷写到磁盘,并锁住数据库。此时数据库只能读,不能写。保证了数据的一致性,在此可以进行复制文件或快照备份。
{
"info" : "now locked against writes, use db.fsyncUnlock() to unlock",
"lockCount" : NumberLong(1),
"seeAlso" : "http://dochub.mongodb.org/core/fsynccommand",
"ok" : 1
}
> db.currentOP() # 查看锁情况
{
"inprog" : [
...
],
"fsyncLock" : true, # MongoDB的fsync进程(负责将修改写入磁盘)正在阻塞写入操作
"info" : "use db.fsyncUnlock() to terminate the fsync write/snapshot lock",
"ok" : 1
}
> db.fsyncUnlock() # 解锁
{ "info" : "fsyncUnlock completed", "lockCount" : NumberLong(0), "ok" : 1 }
> db.currentOP()
{
"inprog" : [
{
"host" : "hdp4:27017",
"desc" : "conn133",
"connectionId" : 133,
"client" : "127.0.0.1:22844",
"appName" : "MongoDB Shell",
"clientMetadata" : {
"application" : {
"name" : "MongoDB Shell"
},
"driver" : {
"name" : "MongoDB Internal Client",
"version" : "4.0.2"
},
"os" : {
"type" : "Linux",
"name" : "CentOS Linux release 7.2.1511 (Core) ",
"architecture" : "x86_64",
"version" : "Kernel 3.10.0-327.el7.x86_64"
}
},
"active" : true,
"currentOpTime" : "2018-10-10T14:03:49.298+0800",
"opid" : 1625425,
"lsid" : {
"id" : UUID("c15d93d9-d9f6-456e-8806-8d2f29dde493"),
"uid" : BinData(0,"d+J7nEzLLc6L5Ue/Mq/KRu3nBl6vz3nsX18GjKuwhYs=")
},
"secs_running" : NumberLong(0),
"microsecs_running" : NumberLong(359),
"op" : "command",
"ns" : "admin.$cmd.aggregate",
"command" : {
"currentOp" : 1,
"lsid" : {
"id" : UUID("c15d93d9-d9f6-456e-8806-8d2f29dde493")
},
"$db" : "admin"
},
"numYields" : 0,
"locks" : {
},
"waitingForLock" : false,
"lockStats" : {
}
}
],
"ok" : 1
}
>
6. 升级MongoDB
升级数据库服务器的必须步骤如下:
- 备份数据并保证备份可用。如果可能,将备份数据恢复到另一个服务器,确认备份是正确的。
- 停止应用,或者将它转移到另一台服务器。
- 停止MongoDB服务器。
- 升级MongoDB服务器的代码至目标版本。
- 使用mongo shell对数据集进行初始的完整性检测。
- 只要有任何地方看起来可能有问题,就使用验证工具检查数据。
- 完成所有的检查之后,重新启动应用。
- 在重新开启服务或者将流量转移回当前服务器时,对应用认真进行测试。
使用复制集的最大特点之一就是:可用于执行滚动升级。该方法被设计用于减小潜在的宕机时间和一些MongoDB大改动(例如升级)所造成的影响。除了下面列出的流程,还应该创建备份并在非生产环境中进行测试。一旦完成详细的调查并保证系统是可恢复的,就可以按照下面的流程进行滚动升级:
- 一次停止一台备库进行升级。
- 在主库上执行rs.stepDown()命令。已经升级成功的某台备库将变成主库。
- 升级原主库。