什么时候需要修复MongoDB Databases?
1. 数据文件损坏,数据不一致。(通常出现在非正常关闭进程后,如断电)
2. 数据文件不断增长,空间利用率低,磁盘空间不足。(MongoDB不会释放remove,drop等操作的空间,除非repair)
3. 优化索引。(数据经常update,delete等)
如何修复MongoDB Replica Set的Databases?
1 - 登入PRIMARY的机器检查replica set里的其他SECONDARY成员的数据是否跟PRIMARY保持同步:
$ mongo primary_host:port
PRIMARY> rs.status()
// 为方便阅读,这里只列出了关键字段
{
"set" : "BackupTest",
"members" : [
{
"_id" : 0,
"name" : "MacintoshdeMacBook-Air.local:30001",
"stateStr" : "PRIMARY",
"optime" : Timestamp(1407767556, 100),
"optimeDate" : ISODate("2014-08-11T14:32:36Z")
},
{
"_id" : 1,
"name" : "MacintoshdeMacBook-Air.local:30002",
"stateStr" : "SECONDARY",
"optime" : Timestamp(1407767556, 100),
"optimeDate" : ISODate("2014-08-11T14:32:36Z")
},
{
"_id" : 2,
"name" : "MacintoshdeMacBook-Air.local:30003",
"stateStr" : "ARBITER"
}
]
}
检查members数组里各个SECONDARY成员的optime是否与PRIMARY的optime保持一致, 接下来的操作将会丢失两者时间差的数据。
2 - 将当前的PRIMARY切换为SECONDARY:
PRIMARY> rs.stepDown() # 切换
2014-08-12T18:45:39.480+0800 DBClientCursor::init call() failed
2014-08-12T18:45:39.483+0800 Error: error doing query: failed at src/mongo/shell/query.js:81
2014-08-12T18:45:39.485+0800 trying reconnect to 127.0.0.1:30001 (127.0.0.1) failed
2014-08-12T18:45:39.486+0800 reconnect 127.0.0.1:30001 (127.0.0.1) ok
SECONDARY> rs.status()
// 为方便阅读,这里只列出了关键字段
{
"set" : "BackupTest",
"members" : [
{
"_id" : 0,
"name" : "MacintoshdeMacBook-Air.local:30001",
"stateStr" : "SECONDARY" // PRIMARY -> SECONDARY
"self" : true
},
{
"_id" : 1,
"name" : "MacintoshdeMacBook-Air.local:30002",
"stateStr" : "PRIMARY" // SECONDARY -> PRIMARY
},
{
"_id" : 2,
"name" : "MacintoshdeMacBook-Air.local:30003",
"stateStr" : "ARBITER"
}
]
}
检查是否切换成功(别的机器是否成为了PRIMARY, 当前机器是否成为了SECONDARY)
3 - 结束当前的SECONDARY(旧的PRIMARY)进程:
SECONDARY> use admin
SECONDARY> db.shutdownServer()
检查各个使用到MongoDB的Clients进程是否能正常查询和写入数据。
4 - 更改原PRIMARY的配置文件,取消replica set模式并更改端口启动
$ sudo vi /etc/mongodb.conf
# 注释掉 replSet = yourReplicaName 和 journal = true
# 并更改 port 至原来不一样的值,例如 port = 30001 -> 30011
5 - 以修复模式启动MongoDB:
$ sudo -umongodb mongod -f /etc/mongodb.conf --repair --repairpath /xxx/xxx # /xxx/xxx 必须是MongoDB dbpath的子目录
修复期间可以通过log文件查看修复进度。
6 - 修复完后,重新以replica set模式启动:
$ sudo vi /etc/mongodb.conf
# 取消刚才replSet = yourReplicaName 和 journal = true 的注释
# 并把port改回原始值
$ sudo -umongodb numactl --interleave=all mongod -f /etc/mongodb.conf #启动
$ mongo old_primary_host:port
SECONDARY> rs.status()
至此,数据库已修复完成, replica set恢复至正常状态。
7 - 假如想将机器重新变成PRIMARY,只需要在现有的PRIMARY机器上重新执行步骤1-2。
如果Replica Set里有多个SECONDARY,MongoDB会在满足条件的基础上随机选取一个变成PRIMARY。
如果想将特定的SECONDARY变成PRIMARY,可以在其他SECONDARY上执行SECONDARY> rs.freeze(60)
防止其在60秒内变成PRIMARY。
P.S: 在修复完数据库,重新启动MongoDB时,有可能出现端口被占用的情况,可以添加系统预留端口,防止MongoDB的端口被随机分配。
$ sudo vim /etc/sysctl.conf
net.ipv4.ip_local_reserved_ports = 30001, 30003-30004
$ sudo sysctl -p