如何在Go语言中基于mongodriver使用mongodump与mongorestore命令
Go 基于 mongo-go-driver 调用 mongodump/mongorestore 实现方案
官方 mongo-go-driver 没有内置 mongodump、mongorestore 的原生调用接口。这两个能力属于MongoDB独立发布的命令行工具集,不属于驱动层实现范畴,生产环境可行的方案是通过Go标准库os/exec调用对应命令行二进制,同时可以直接复用mongo driver初始化时的连接配置,避免重复维护连接参数。
前置依赖
- 运行Go程序的服务器/容器内,提前安装和Mongo实例版本匹配的MongoDB Database Tools,确保
mongodump、mongorestore可执行文件在系统PATH中,或者在代码中指定二进制的绝对路径 - 连接MongoDB使用的账号,提前分配对应权限:执行mongodump需要目标库的读权限,执行mongorestore需要目标库的写、集合创建、索引创建权限
具体实现
1. 复用driver连接参数,避免硬编码
如果你已经通过mongo driver完成了客户端初始化,可以直接从客户端配置中提取连接信息,不需要手动拆分连接串:
package main import ( "context" "fmt" "os/exec" "time" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readpref" ) // 存储Mongo连接配置,供dump/restore调用 type MongoConfig struct { Host string Port int Username string Password string AuthDB string } var mongoConf MongoConfig func initMongoClient(uri string) (*mongo.Client, error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() clientOpts := options.Client().ApplyURI(uri) client, err := mongo.Connect(ctx, clientOpts) if err != nil { return nil, err } if err = client.Ping(ctx, readpref.Primary()); err != nil { return nil, err } // 从解析后的配置中提取连接参数 mongoConf.Host = clientOpts.Hosts[0].Host mongoConf.Port = int(clientOpts.Hosts[0].Port) if clientOpts.Auth != nil { mongoConf.Username = clientOpts.Auth.Username mongoConf.Password = clientOpts.Auth.Password if clientOpts.Auth.AuthSource != "" { mongoConf.AuthDB = clientOpts.Auth.AuthSource } else { // 未指定auth源时默认用admin mongoConf.AuthDB = "admin" } } return client, nil }
2. 调用mongodump实现备份
// MongoDump 执行mongodump备份 // dbName: 要备份的库名,传空则备份全实例 // collectionName: 要备份的集合名,传空则备份整个库 // outputPath: 备份文件输出目录 func MongoDump(dbName, collectionName, outputPath string) error { // 组装命令参数 args := []string{ "--host", mongoConf.Host, "--port", fmt.Sprintf("%d", mongoConf.Port), "-u", mongoConf.Username, "-p", mongoConf.Password, "--authenticationDatabase", mongoConf.AuthDB, "-o", outputPath, } if dbName != "" { args = append(args, "-d", dbName) } if collectionName != "" { args = append(args, "-c", collectionName) } // 超时时间根据备份数据量调整,示例配置1小时 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour) defer cancel() cmd := exec.CommandContext(ctx, "mongodump", args...) // 捕获标准输出和错误输出,方便排查问题 cmdOutput, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("mongodump执行失败: %w, 输出日志: %s", err, string(cmdOutput)) } return nil }
3. 调用mongorestore实现恢复
// MongoRestore 执行mongorestore恢复 // dbName: 要恢复到的目标库名 // inputPath: 备份文件所在路径 // drop: 恢复前是否删除已存在的集合 func MongoRestore(dbName, inputPath string, drop bool) error { args := []string{ "--host", mongoConf.Host, "--port", fmt.Sprintf("%d", mongoConf.Port), "-u", mongoConf.Username, "-p", mongoConf.Password, "--authenticationDatabase", mongoConf.AuthDB, } if dbName != "" { args = append(args, "-d", dbName) } if drop { args = append(args, "--drop") } // 最后追加备份路径参数 args = append(args, inputPath) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour) defer cancel() cmd := exec.CommandContext(ctx, "mongorestore", args...) cmdOutput, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("mongorestore执行失败: %w, 输出日志: %s", err, string(cmdOutput)) } return nil }
注意事项
- 不要尝试自己实现dump/restore逻辑:BSON格式解析、索引一致性、事务快照等逻辑复杂度极高,官方工具已经做了全量兼容,自行实现很容易出现备份损坏、数据不一致的问题
- 如果是副本集、分片集群场景,只需要在参数里追加
--replicaSet等对应配置参数即可,参数提取逻辑和host等字段一致,副本集多节点场景把hosts列表拼接为逗号分隔的字符串传入即可 - 大库备份/恢复时一定要设置合理的超时时间,不要用默认短超时导致命令被中途终止
- 安全要求高的生产环境不要把密码明文放在命令参数中,可以通过
--stdin参数传递密码,避免密码出现在进程列表中 - 执行命令的运行用户需要对备份输出目录、备份输入路径有完整读写权限
内容的提问来源于stack exchange,提问作者TheLegenD
相关产品推荐
相关产品推荐

