参考
mongodb 备份指定时间段的数据:https://blog.51cto.com/u_16213337/7146774
MongoDB备份以及还原(全量+增量):https://devpress.csdn.net/mongodb/6304939fc67703293080d1cb.html
查看bson文件可以先将bson文件转为json
bsondump cook.bson --outFile=cook.json
完整代码:dbRecoverContinue.js
思路:先还原当日的全量副本,之后循环还原 开始到结束的之间小时段数据
补充:副本集若开了访问权限,需要在下方每个指令中加上: -u 用户名 -p 密码 --authenticationDatabase 权限存放库
var path = require("path"),
fs = require("fs-extra"),
exec = require("child_process").exec,
_ = require("lodash"),
async = require("async"),
moment = require("moment"),
config = {
dateFormate: "YYYYMMDD",
dbBackupPath: "/tmp/backup",
suffix: "",
recoverDate: "20240516", //恢复库的日期
recoverStartHours: 0, //恢复库的开始小时
recoverEndHours: 4, //恢复库的结束小时
},
Recover = {};
/**
* [init 数据库备份服务]
* @param {[type]} options [description]
* @return {[type]} [description]
*/
Recover.init = function (options) {
return new Promise((resolve, reject) => {
try {
//恢复的日期
var recoverDatePath = options.recoverDate | config.recoverDate;
var dbBackupPath = options.path || config.dbBackupPath, //数据库备份父级目录
dbHost = options.host, //数据连接
dbName = options.name, //数据库名称
suffix = options.suffix || config.suffix, //存储目录后缀
todayRecoverName = getDatePath(recoverDatePath, dbName, suffix), //需要恢复目录名
todayRecoverPath = path.join(dbBackupPath, todayRecoverName);
if (!dbHost) {
console.log("[参数缺失] dbHost");
throw new Error("[参数缺失] dbHost");
}
if (!dbName) {
console.log(`[恢复数据库] 所有库`);
} else {
console.log(`[恢复数据库] ${dbName}`);
}
if (!fs.existsSync(todayRecoverPath)) {
console.log("[不存在备份目录] %s", todayRecoverPath);
throw new Error("查询的日期备份目录不存在,请检查备份日志是否有备份");
}
console.log(
"-------------------------------------------- 1.恢复数据库 -------------------------------------------"
);
console.log("[开始恢复] %s %s ", dbHost, dbName ? dbName : "所有库");
var cmdStr =
"mongorestore -h " +
dbHost +
(dbName ? " -d " + dbName : "") +
" --dir " +
todayRecoverPath +
"" +
(dbName ? "/" + dbName : "");
console.log("[开始执行指令] %s", cmdStr);
exec(cmdStr, async function (err) {
if (!err) {
console.log("[指令执行成功] %s", todayRecoverPath);
//如果recoverEndHours有值
if (options.recoverEndHours) {
let endHours = options.recoverEndHours;
let startHours = options.recoverStartHours || 0;
//开始按顺序增量还原
await spikeRecoverHours(
dbHost,
todayRecoverPath,
recoverDatePath,
startHours,
endHours
).catch((spikeErr) => {
throw new Error(spikeErr.message);
});
}
resolve();
} else {
console.log(err);
console.log("[指令执行失败] %s", cmdStr);
throw new Error(err.message);
}
});
} catch (err) {
reject(err);
}
});
};
//循环增量恢复
async function spikeRecoverHours(
dbHost,
todayRecoverPath,
recoverDatePath,
start,
end
) {
let currentMonth = "";
currentMonth = start < 10 ? "0" + start : start;
var hoursCmd = `mongorestore -h ${dbHost} --dir ${todayRecoverPath}/${recoverDatePath}${currentMonth}/local/oplog.rs.bson`;
console.log("[指令执行] %s", hoursCmd);
exec(hoursCmd, async function (err) {
if (!err) {
console.log(
`[增量还原 ${start}时成功] %s`,
`${recoverDatePath}${currentMonth}`
);
if (++start <= end) {
await spikeRecoverHours(
dbHost,
todayRecoverPath,
recoverDatePath,
start,
end
);
}
} else {
console.log(
`[增量还原 ${start}时失败] %s`,
`${recoverDatePath}${currentMonth}`
);
throw new Error(err.message);
}
});
}
function getDatePath(dateName, dbName, suffix) {
return `${dateName}-${dbName ? dbName : "all"}${suffix ? "-" + suffix : ""}`;
}
module.exports = Recover;