从 MySQL 到 MongoDB:80 万系统日志(sys_log)平滑迁移完整实战(含 Windows 环境 mongoimport 安装与避坑)

标签:MongoDB MySQL Spring Boot 数据迁移 mongoimport MongoDB Compass 日志系统


一、背景与动机

系统操作日志表 sys_log 随着业务增长,在 MySQL 中积累了近 80 万条记录。面临几个痛点:

  • 列表查询和模糊检索越来越慢;
  • 日志字段(paramsjson_result)偏半结构化,关系表约束收益低;
  • 写入并发上来后,希望降低对业务主库的影响。

MongoDB 的文档模型、索引能力和横向扩展特性非常适合日志/审计类数据。本文记录从 MySQL/CSV → MongoDB​ 的一次性迁移全过程,包含 Windows 环境下工具链安装、字段映射、高速导入、类型校正、索引重建以及 Spring Boot 对接。

目标库:kms_logdb

目标集合:sys_log

连接方式:用户名/密码,认证库 admin


二、环境准备与工具安装(Windows 重点)

很多同学在执行导入时会遇到:

复制代码
'mongoimport' 不是内部或外部命令,也不是可运行的程序或批处理文件。

这是因为 MongoDB Server/Compass 默认不携带 mongoimport 。它是独立发布的 MongoDB Database Tools​ 里的工具。

2.1 安装 MongoDB Database Tools(必须)

下载地址:https://www.mongodb.com/try/download/database-tools

选择 Windows / MSI 安装包,一路下一步。默认路径类似:

复制代码
C:\Program Files\MongoDB\Tools\100\bin\

里面包含:

复制代码
mongoimport.exe
mongodump.exe
mongorestore.exe
mongostat.exe
...

2.2 配置系统环境变量 PATH

  1. 控制面板 → 系统 → 高级系统设置 → 环境变量

  2. 系统变量中找到 Path → 编辑 → 新建

  3. 填入:

    C:\Program Files\MongoDB\Tools\100\bin\

  4. 确定保存,重新打开 CMD/PowerShell

  5. 验证:

    mongoimport --version

能输出版本号即成功。

如果不想配置环境变量,后面所有命令都要写完整路径,例如:

"C:\Program Files\MongoDB\Tools\100\bin\mongoimport.exe" ...

2.3 MongoDB Compass(可选,但强烈推荐)

用于可视化连接、查看数据、校验字段、建索引和抽样调试。你如果已经连上 10.11.254.56:27017localhost:27017,就可以用它做后期校验。

注意:Compass 可以导入小批量 CSV,但 80w 数据不建议用它导,容易卡顿/超时,主力仍是 mongoimport


三、源数据准备:CSV 表头与字段映射

假设从 MySQL 或 Excel 拿到的原始 CSV 表头是:

复制代码
id,username,operation,method,params,json_result,time,ip,create_date

MongoDB/Spring Boot 实体我们期望:

复制代码
@Document(collection = "sys_log")
public class SysLogEntity {
    @Id
    private String id;          // MongoDB 自动生成 _id
    private String username;
    private String operation;
    private String method;
    private String params;
    private String jsonResult;  // 不是 json_result
    private Long time;
    private String ip;
    private Date createDate;    // 不是 create_date
}

所以 CSV 最终表头必须改为:

复制代码
username,operation,method,params,jsonResult,time,ip,createDate

操作步骤:

  1. 删除 id 列(让 MongoDB 自动生成 _id

  2. json_resultjsonResult

  3. create_datecreateDate

  4. 保存为标准 CSV(推荐 UTF-8,逗号分隔)

  5. 文件路径:

    C:\Users\Lenovo\Desktop\sys_log.csv

日期格式尽量是:

复制代码
2025-02-07 15:55:32

如果是 Excel 导出的 2/7/2025 15:55:32,后面用 $dateFromString 处理。


四、MongoDB 侧初始化集合与校验规则

mongosh 或 Compass 的 Shell/查询窗口执行:

复制代码
db = db.getSiblingDB('kms_logdb');

var SYS_LOG_VALIDATOR = {
  $jsonSchema: {
    bsonType: "object",
    required: ["_id", "username", "operation", "method", "params", "jsonResult", "time", "ip", "createDate"],
    properties: {
      _id:        { bsonType: "objectId" },
      username:   { bsonType: "string" },
      operation:  { bsonType: "string" },
      method:     { bsonType: "string" },
      params:     { bsonType: "string" },
      jsonResult: { bsonType: "string" },
      time:       { bsonType: ["long", "int"] },
      ip:         { bsonType: "string" },
      createDate: { bsonType: "date" }
    }
  }
};

if (db.getCollectionNames().indexOf('sys_log') < 0) {
  db.createCollection('sys_log', {
    validator: SYS_LOG_VALIDATOR,
    validationLevel: "moderate",
    validationAction: "warn"
  });
} else {
  db.runCommand({
    collMod: "sys_log",
    validator: SYS_LOG_VALIDATOR,
    validationLevel: "moderate",
    validationAction: "warn"
  });
}

print('✅ 集合初始化完成:kms_logdb.sys_log');

validationLevel: "moderate" + validationAction: "warn" 表示已有文档不强制打断,只告警,适合迁移场景。


五、导入前:删除旧索引,提升写入速度

80w 数据导入时,如果已有索引会大幅拖慢写入。

复制代码
db.sys_log.dropIndexes();

六、使用 mongoimport 高速导入

CMD 中执行(已配 PATH 的写法):

复制代码
mongoimport ^
  --host=127.0.0.1 ^
  --port=27017 ^
  --username=root ^
  --password=test ^
  --authenticationDatabase=admin ^
  --db=kms_logdb ^
  --collection=sys_log ^
  --type=csv ^
  --headerline ^
  --file="C:\Users\Lenovo\Desktop\sys_log.csv" ^
  --numInsertionWorkers=4 ^
  --batchSize=5000

如果没配 PATH,用:

复制代码
"C:\Program Files\MongoDB\Tools\100\bin\mongoimport.exe" ^
  --host=127.0.0.1 ^
  --port=27017 ^
  --username=root ^
  --password=test ^
  --authenticationDatabase=admin ^
  --db=kms_logdb ^
  --collection=sys_log ^
  --type=csv ^
  --headerline ^
  --file="C:\Users\Lenovo\Desktop\sys_log.csv" ^
  --numInsertionWorkers=4 ^
  --batchSize=5000

参数说明:

  • --headerline:使用 CSV 第一行作为字段名
  • --numInsertionWorkers=4:并发写入,提升吞吐
  • --batchSize=5000:每批写入量
  • 密码含 @,用参数方式传,不要拼 URI,避免解析错误

七、导入后类型校正(非常关键)

CSV 导入后,数字和日期往往会被当成字符串/int,需要校正。

7.1 time 统一为 long

复制代码
db.sys_log.updateMany(
  { time: { $type: "int" } },
  [{ $set: { time: { $toLong: "$time" } } }]
);

7.2 createDate 转 Date

如果是 2025-02-07 15:55:32

复制代码
db.sys_log.updateMany(
  { createDate: { $type: "string" } },
  [{ $set: { createDate: { $toDate: "$createDate" } } }]
);

如果是 2/7/2025 15:55:32

复制代码
db.sys_log.updateMany(
  { createDate: { $type: "string" } },
  [{
    $set: {
      createDate: {
        $dateFromString: {
          dateString: "$createDate",
          format: "%d/%m/%Y %H:%M:%S"
        }
      }
    }
  }]
);

八、重建索引

对齐原 MySQL 查询习惯:

复制代码
db.sys_log.createIndex({ createDate: -1 }, { name: 'idx_create_date' });
db.sys_log.createIndex({ operation: 1 }, { name: 'idx_operation' });
db.sys_log.createIndex({ username: 1 }, { name: 'idx_username' });
db.sys_log.createIndex({ username: 1, operation: 1 }, { name: 'idx_username_operation' });
db.sys_log.createIndex({ createDate: -1, _id: -1 }, { name: 'idx_create_date_id' });

如果日志只需保留 90 天,可加 TTL(可选):

复制代码
db.sys_log.createIndex(
  { createDate: 1 },
  { name: 'ttl_create_date', expireAfterSeconds: 90 * 24 * 3600 }
);

九、数据校验

复制代码
db.sys_log.countDocuments()
db.sys_log.findOne()

db.sys_log.aggregate([
  { $sample: { size: 10 } },
  {
    $project: {
      timeType: { $type: "$time" },
      dateType: { $type: "$createDate" },
      username: 1,
      operation: 1,
      createDate: 1
    }
  }
]);

期望:

  • countDocuments() ≈ MySQL 的 SELECT COUNT(*)
  • timeTypelong
  • dateTypedate

在 Compass 里也可以直接打开 kms_logdb.sys_log 看文档结构和索引。


十、Spring Boot 配置对接

复制代码
spring:
  data:
    mongodb:
      authentication-database: admin
      host: 127.0.0.1
      port: 27017
      username: root
      password: test
      database: kms_logdb

实体类:

复制代码
@Document(collection = "sys_log")
public class SysLogEntity {

    @Id
    private String id;

    private String username;
    private String operation;
    private String method;
    private String params;
    private String jsonResult;
    private Long time;
    private String ip;
    private Date createDate;

    // getter / setter
}

Repository:

复制代码
public interface SysLogRepository extends MongoRepository<SysLogEntity, String> {
    Page<SysLogEntity> findByUsernameContainingOrOperationContaining(
        String username, String operation, Pageable pageable);
}

字段名与 CSV/MongoDB 完全一致,无需额外映射。


十一、常见问题与坑

1. mongoimport 不是命令

安装 MongoDB Database Tools 并配 PATH,或用完整 exe 路径。

2. 密码含特殊字符(如 @

--password=xxx 参数形式,不要拼连接字符串 URI。

3. 日期导入后是字符串

导入后用 $toDate$dateFromString 校正。

4. 字段名下划线/驼峰不一致

MySQL: json_result, create_date

MongoDB/Java: jsonResult, createDate

CSV 表头必须提前改好。

5. 导入慢

dropIndexes(),再用 --numInsertionWorkers--batchSize

6. Compass 能导入吗?

能,但适合小数据/校验。80w 条请用 mongoimport


十二、总结

完整链路:

复制代码
MySQL/Excel CSV 准备表头
        ↓
安装 mongoimport / Compass 连接校验
        ↓
mongosh 初始化 sys_log + validator
        ↓
dropIndexes()
        ↓
mongoimport 导入 80w
        ↓
校正 time / createDate 类型
        ↓
重建索引
        ↓
Spring Boot 对接 kms_logdb

迁移后日志查询和写入性能明显提升,MongoDB 的文档结构也更贴合日志这类半结构化数据。

后续可扩展:

  • TTL 自动清理历史日志
  • 异步批量写入
  • MySQL/MongoDB 双写平滑切换
  • 按时间分片/归档

希望这篇能帮你少踩 Windows 工具链和字段映射的坑。

相关推荐
这个DBA有点耶2 小时前
InnoDB页结构深入:页分裂、页合并、填充因子——B+树底层机制全解析
数据库·mysql·架构
山岚的运维笔记2 小时前
mysql 专业笔记 -- 第 36 章:MySQL 管理
运维·数据库·笔记·后端·mysql·oracle·dba
霸道流氓气质4 小时前
SQL 里的 AND / OR 优先级陷阱:一个括号引发的“数据越界“
mysql
爱奥尼欧6 小时前
【MySQL】建库就是建目录?字符集校验规则、备份恢复与alter改表实操
mysql
大虾别跑7 小时前
mysql5.7升级
mysql
geovindu7 小时前
sql: Transaction & Concurrency Patterns using mysql 9.0
mysql·数据库开发·数据库架构
敲代码的瓦龙8 小时前
Jetpack?DataBinding!!!
android·java·开发语言·mysql·android-studio
想念是会呼吸的鱼8 小时前
MySQL 常用语法整理
sql·mysql
不正经的码狗8 小时前
MySQL 免安装教程|安装不报错
mysql