一、备份的目的¶
- 防止硬件故障引起的数据丢失
- 防止人为错误误删数据
- 时间回溯
- 监管要求
二、备份机制与备份方式介绍:¶
MongoDB的备份机制:
- 延迟节点备份
- 全量备份 + oplog增量
最常见的全量备份方式包括:
- mongodump
- 复制数据文件
- 文件系统快照


三、mongodump和 mongorestore¶
3.1 介绍¶
mongodump能够在 Mongodb运行时进行备份,它的工作原理是对运行的 Mongodb做查询,然后将所有查到的 文档写入磁盘。可以备份单独的数据库、集合甚至集合中的子集。
存在问题:
- 备份恢复的速度较慢
- 使用 mongodump产生的备份不一定是数据库的实时快照
- 在备份时可能会对其它客户端性能产生不利的影响
3.2 下载¶
从 MongoDB 4.4开始, MongoDB数据库工具现在从 MongoDB服务器单独发布,使用自己的版本,初始版本为 100.0.0。以前,这些工具是与 MongoDB服务器一起发布的,并使用匹配的版本控制。 MongoDB数据库工具是一组用于 MongoDB部署的命令行实用程序。数据库工具包括以下二进制文件 :mongodump、 mongoexport、 mongoimport、 mongorestore、 mongostat、 mongotop
cd /data/download
wget https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel70-x86_64-100.10.0.tgz
tar zxvf mongodb-database-tools-rhel70-x86_64-100.10.0.tgz
mv mongodb-database-tools-rhel70-x86_64-100.10.0 mongodb-database-tools
3.3 mongodump参数¶
$ mongodump help
参数说明:
- -h:指明数据库宿主机的 IP
- -u:指明数据库的用户名
- -p:指明数据库的密码
- -d:指明数据库的名字
- -c:指明 collection的名字
- -o:指明到要导出的文件名
- -q:指明导出数据的过滤条件
- -j, numParallelCollections= number of collections to dump in parallel (4 by default) #要并行转储的集合数量 (默认为 4)
- --oplog 备份的同时备份 oplog
3.4 mongodump和 mongorestore基本使用¶
1、全库备份
mkdir -p /data/backup/mongodb
$ /data/download/mongodb-database-tools/bin/mongodump -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -o /data/backup/mongodb
2、备份 app库
$ /data/download/mongodb-database-tools/bin/mongodump -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -d app -o /data/backup/mongodb/150-app
3、备份 app库下的 log集合
$ /data/download/mongodb-database-tools/bin/mongodump -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -d app -c log -o /data/backup/mongodb/150-app-log
4、压缩备份
$ /data/download/mongodb-database-tools/bin/mongodump -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -d app -o /data/backup/mongodb/gzip --gzip
[root@dev1 app]# pwd
/data/backup/mongodb/gzip/app
[root@dev1 app]# ls
a.bson.gz a.metadata.json.gz c.bson.gz c.metadata.json.gz fruit.bson.gz fruit.metadata.json.gz log.bson.gz log.metadata.json.gz
5、全备中恢复单库
$ /data/download/mongodb-database-tools/bin/mongorestore -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase=admin -d app1 /data/backup/mongodb/app
6、全备中恢复单表
$ /data/download/mongodb-database-tools/bin/mongorestore -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase=admin -d app -c log1 /data/backup/mongodb/app/log.bson
恢复压缩的数据
$ /data/download/mongodb-database-tools/bin/mongorestore -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase=admin -d app -c log2 /data/backup/mongodb/gzip/app/log.bson.gz --gzip
7、 drop表示恢复的时候把之前的集合 drop掉 (危险 )
$ /data/download/mongodb-database-tools/bin/mongorestore -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase=admin -d app --drop /data/backup/mongodb/app
3.5 mongodump和 mongorestore高级企业应用( oplog)¶
--oplog use oplog for taking a point-in-time snapshot
注意:这是 replica set模式专用
oplog介绍
在 replica set中 oplog是一个定容集合( capped collection),它的默认大小是磁盘空间的 5%(可以 通过 oplogSizeMB参数修改 ).
-
位于 local库的 db.oplog.rs
-
其中记录的是整个 mongod实例一段时间内数据库的所有变更(插入 /更新 /删除)操作。
-
当空间用完时新记录自动覆盖最老的记录。
-
其覆盖范围被称作 oplog时间窗口。
oplog企业级应用
(1)实现热备,在备份时使用 oplog选项
注:为了演示效果我们在备份过程,模拟数据插入
(2)准备测试数据
repl:PRIMARY> use test
repl:PRIMARY> for(var i = 1 ;i < 100; i++) {db.foo.insert({a:i});}
repl:PRIMARY> use local
repl:PRIMARY> db.oplog.rs.find({"op":"i"}).pretty()
{
"op" : "i",
"ns" : "test.foo",
"ui" : UUID("5c0217c6-1f82-4a19-be40-1bd65b1fd4e3"),
"o" : {
"_id" : ObjectId("634d3d284e2addec5fcad718"),
"a" : 3
},
"ts" : Timestamp(1666006312, 4),
"t" : NumberLong(1),
"v" : NumberLong(2),
"wall" : ISODate("2022-10-17T11:31:52.906Z")
}
oplog 配合 mongodump实现热备
#备份
/data/download/mongodb-database-tools/bin/mongodump -uroot -h192.168.1.153 -proot123456 --port 27018 --authenticationDatabase admin --oplog -o /data/backup/mongodb/repl
作用介绍:--oplog 会记录备份过程中的数据变化。会以oplog.bson保存下来
#恢复
/data/download/mongodb-database-tools/bin/mongorestore -uroot -h192.168.1.153 -proot123456 --port 27018 --oplogReplay /data/backup/mongodb/repl
!!!!!!!!!!oplog高级应用 ==========binlog应用
背景:每天 0点全备, oplog恢复窗口为 48小时
某天,上午 10点 world.city 业务表被误删除。
恢复思路:
0、停应用
2、找测试库
3、恢复昨天晚上全备
4、截取全备之后到 world.city误删除时间点的 oplog,并恢复到测试库
5、将误删除表导出,恢复到生产库
恢复步骤:
模拟故障环境:
1、全备数据库
模拟原始数据
/data/download/mongosh/bin/mongosh mongodb://192.168.1.153:27018/admin
/data/download/mongosh/bin/mongosh "mongodb://root:root123456@192.168.1.153:27018/admin"
> use wo
> for(var i = 1 ;i < 20; i++) {
db.ci.insert({a: i});
}
全备:
/data/download/mongodb-database-tools/bin/mongodump -uroot -h192.168.1.153 -proot123456 --port 27018 --authenticationDatabase admin --oplog -o /data/backup/mongodb/repl_20240801
oplog功能:在备份同时,将备份过程中产生的日志进行备份
文件必须存放在 /data/backup/mongodb/repl_20240801下,自动命令为oplog.bson
再次模拟数据
db.ci1.insert({id:1})
db.ci2.insert({id:2})
2、晚上17:55点:删除wo库下的ci表 //19:55时刻,误删除
db.ci.drop()
show tables;
3、备份现有的oplog.rs表
/data/download/mongodb-database-tools/bin/mongodump -uroot -h192.168.1.153 -proot123456 --port 27018 --authenticationDatabase admin -d local -c oplog.rs -o /data/backup/mongodb/repl_20240801
4、截取oplog并恢复到drop之前的位置
更合理的方法:登陆到原数据库
mongo 192.168.1.153:27018/admin -uroot -proot123456
my_repl:PRIMARY> use local
repl:PRIMARY> db.oplog.rs.find({ op:"c","o.drop":"ci","ts" : { "$gte" : Timestamp(1722678900, 1) } }).pretty()
{
"op" : "c",
"ns" : "wo.$cmd",
"ui" : UUID("1059940d-5d32-42f7-b1ce-ce0cc19d1921"),
"o" : {
"drop" : "ci"
},
"o2" : {
"numRecords" : 19
},
"ts" : Timestamp(1722678913, 1),
"t" : NumberLong(1),
"v" : NumberLong(2),
"wall" : ISODate("2024-08-03T09:55:13.492Z")
}
或者 repl:PRIMARY> db.oplog.rs.find({op:"c"}).sort({ts:-1}).limit(1)获取到oplog误删除时间点位置:
1722678913, 1
5、恢复备份 +应用oplog
[mongod@db03 backup]$ cd /data/backup/mongodb/repl_20240803/local
[mongod@db03 local]$ ls
oplog.rs.bson oplog.rs.metadata.json
[mongod@db03 local]$ cp oplog.rs.bson ../oplog.bson #覆盖原来的 oplog.bson
rm -rf /data/backup/mongodb/repl_20240803/local/
/data/download/mongodb-database-tools/bin/mongorestore -uroot -h192.168.1.153 -proot123456 --port 27018 --oplogReplay --oplogLimit "1722678913:1" --drop /data/backup/mongodb/repl_20240803/
6、查看恢复的数据
/data/mongodb/mongodb_repl/bin/mongo 192.168.1.153:27018/admin -uroot -proot123456
repl:PRIMARY> use wo
repl:PRIMARY> show tables
ci
ci1
ci2
repl:PRIMARY> db.ci.count()
19
7、分片集群的备份思路
Sharding备份形式基本上可以分为两种,分别是异构备份恢复和同构备份恢复。
(1)异构备份恢复
恢复出来的形态和原来不同
方案:
- 使用 mongodump工具链接 mongos进行备份
问题:
- 逻辑备份效率低,只适用于数据量小的场景
- 恢复出来后需要重新分片
(2)同构备份恢复
恢复出来的形态与原来的架构完全一致
方案:
- 分别备份 shard、configserver
问题:
- 很难取得一个一致的 sharding备份
- 备份出来的数据时间不一致
- 影响因素:
- 备份过程中外部的修改
- 备份过程中内部的修改:内部迁移(chunk迁移)/
(3)其他方案
a.使用 Ops Manager
b.
balancer 关闭--->
同一时刻config、shard其中一个节点脱离集群--->
开始备份节点数据 --->
把节点恢复到集群
四、表导入导出常用工具¶
mongoexport/mongoimport
针对库中的表,导入/导出的是JSON格式或者CSV格式,而mongodump/mongorestore针对库,导入/导出的是BSON格式。
应用场景:
mongoexport/mongoimport: json csv
1、异构平台迁移 mysql <---> mongodb
2、同平台,跨大版本: mongodb 5 ----> mongodb 6
mongodump/mongorestore
1、日常备份恢复时使用
4.1 导出工具 mongoexport¶
1、定义
Mongodb中的 mongoexport工具可以把一个 collection导出成 JSON格式或 CSV格式的文件。可以通过参数指定导出的数据项,也可以根据指定的条件导出数据。
(1)版本差异较大
(2)异构平台数据迁移
2、用法
mongoexport具体用法如下所示:
$ mongoexport --help
参数说明:
-h: 指明数据库宿主机的 IP-u: 指明数据库的用户名-p: 指明数据库的密码-d: 指明数据库的名字-c: 指明 collection的名字-f: 指明要导出那些列-o: 指明到要导出的文件名-q: 指明导出数据的过滤条件--authenticationDatabase admin
3、示例
(1)单表备份至 json格式
> use test
> for(i=0;i<100;i++){ db.log.insert({"uid":i,"name":"mongodb","age":6,"date":new Date()}); }
$ /data/download/mongodb-database-tools/bin/mongoexport -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -d test -c log -o /data/backup/mongodb/mongoexport/log.json
注:备份文件的名字可以自定义,默认导出了JSON格式的数据。
(2)单表备份至 csv格式
如果我们需要导出CSV格式的数据,则需要使用--type=csv参数:
$ /data/download/mongodb-database-tools/bin/mongoexport -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -d test -c log --type=csv -f uid,name,age,date -o /data/backup/mongodb/mongoexport/log.csv
4.2 导入工具 mongoimport¶
1、定义
Mongodb中的 mongoimport工具可以把一个特定格式文件中的内容导入到指定的 collection中。该工具可以导入 JSON格式数据,也可以导入 CSV格式数据。具体使用如下所示:
2、用法
$ mongoimport --help
参数说明:
-h: 指明数据库宿主机的 IP-u: 指明数据库的用户名-p: 指明数据库的密码-d: 指明数据库的名字-c: 指明 collection的名字-f: 指明要导入那些列-j, --numInsertionWorkers=<number> number of insert operations to run concurrently (defaults to 1)
并行
3、示例
数据恢复:
(1)恢复json格式表数据到log1
$ /data/download/mongodb-database-tools/bin/mongoimport -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -d test -c log1 /data/backup/mongodb/mongoexport/log.json
(2)恢复csv格式的文件到log2
上面演示的是导入 JSON格式的文件中的内容,如果要导入 CSV格式文件中的内容,则需要通过 type参数指 定导入格式,具体如下所示:
1、csv格式的文件头行,有列名字
--headerline:指明第一行是列名,不需要导入
$ /data/download/mongodb-database-tools/bin/mongoimport -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -d test -c log2 --type=csv --headerline --file /data/backup/mongodb/mongoexport/log.csv
2、csv格式的文件头行,没有列名字
$ /data/download/mongodb-database-tools/bin/mongoimport -uroot -h192.168.1.153 -p000000 --port 27017 --authenticationDatabase admin -d test -c log3 -j 4 --type=csv -f id,name,age,date --file /data/backup/mongodb/mongoexport/log.csv
4、异构平台迁移案例
mysql -----> mongodb
oldboy_test数据库下info_area表进行导出,导入到mongodb
(1)mysql开启安全路径
vim /etc/my.cnf --->添加以下配置
secure-file-priv=/data/backup/
--重启数据库生效
/etc/init.d/mysqld restart
(2)导出mysql的city表数据
mysql -uroot -h 192.168.1.150 -p000000 -P3307
mysql> use oldboy_test
mysql> select * from info_area into outfile '/tmp/info_area.csv' fields terminated by ',';
Query OK, 20104 rows affected (0.03 sec)
(3)获取列信息
mysql> select table_name,group_concat(column_name) from information_schema.columns where table_schema='oldboy_test' and table_name='info_area' group by table_name order by null ;
+------------+---------------------------+
| table_name | group_concat(column_name) |
+------------+---------------------------+
| info_area | id,name,rel_id,pid,level |
+------------+---------------------------+
1 row in set (0.00 sec)
mysql> select * from oldboy_test.info_area limit 1;
+-------+--------+--------+-----+-------+
| id | name | rel_id | pid | level |
+-------+--------+--------+-----+-------+
| 10000 | 北京 | 10000 | 0 | 1 |
+-------+--------+--------+-----+-------+
1 row in set (0.00 sec)
(4)在mongodb中导入备份
$ /data/download/mongodb-database-tools/bin/mongoimport -uroot -h192.168.1.150 -p000000 --port 27017 --authenticationDatabase admin -d test -c info_area --type=csv -f id,name,rel_id,pid,level --file /tmp/info_area.csv
> use test
> db.info_area.find()
{ "_id" : ObjectId("634be046c0612fd495ae2c8a"), "id" : 10000, "name" : "北京", "rel_id" : 10000, "pid" : 0, "level" : 1 }
5、如何将MySQL大量表迁移到MongoDB
(1)批量从MySQL导出某个库下的多张表
# mysqldump -h192.168.1.150 -P3307 -uroot -p000000 --single-transaction oldboy_test --fields-terminated-by=',' --fields-enclosed-by '"' -T /tmp/backup/
# cd /tmp/backup
# rm -rf /tmp/backup/*.sql
# find ./ -name "*.txt" | awk -F "." '{print $2}' | xargs -i -t mv ./{}.txt ./{}.csv
(2)拼接语句
mysql> select concat("/data/download/mongodb-database-tools/bin/mongoimport -uroot -h192.168.1.150 -p000000 --port 27017 --authenticationDatabase admin -d ",table_schema, " -c ",table_name ," --type=csv "," -f ", group_concat(column_name) ," --file /tmp/backup/",table_name ,".csv") from information_schema.columns where table_schema="oldboy_test" group by table_name;
(3)将语句写入文件 import.sh
[root@dev0 backup]# mysql -h192.168.1.150 -P3307 -uroot -p000000 -D oldboy_test -Ne 'select concat("/data/download/mongodb-database-tools/bin/mongoimport -uroot -h192.168.1.150 -p000000 --port 27017 --authenticationDatabase admin -d ",table_schema, " -c ",table_name ," --type=csv "," -f ", group_concat(column_name) ," --file /tmp/backup/",table_name ,".csv") from information_schema.columns where table_schema="oldboy_test" group by table_name;' > /tmp/backup/import.sh
[root@dev0 backup]# ll -h
总用量 1.1M
-rw-r--r--. 1 root root 1.2K 10月 16 19:05 import.sh
-rw-rw-rw-. 1 mysql mysql 515 10月 16 18:53 info_area_20240801.csv
-rw-rw-rw-. 1 mysql mysql 1.9K 10月 16 18:53 info_area_bak.csv
-rw-rw-rw-. 1 mysql mysql 1.1M 10月 16 18:53 info_area.csv
-rw-rw-rw-. 1 mysql mysql 19 10月 16 18:53 repl_ignore_test.csv
(4)导入数据
[mongod@db01 backup]$ sh import.sh
#登录mongo查看库表信息
> show dbs
admin 0.000GB
app 0.001GB
config 0.000GB
local 0.000GB
oldboy_test 0.001GB
test 0.002GB
> use oldboy_test
switched to db oldboy_test
> show tables;
info_area
info_area_20240801
info_area_bak
repl_ignore_test