Files
曾志威 30385fc34b
continuous-integration/drone Build is failing
feat: initialize syncdb web service MVP
2026-09-06 14:06:16 +08:00

9.4 KiB

syncdb 产品与技术设计

1. 产品定位

syncdb 是基于 Go 的轻量级 Web 数据库同步服务,支持 MySQL 和 MongoDB,面向开发、测试和运维环境。

支持范围

来源 目标 范围
MySQL MySQL MVP
MongoDB MongoDB MVP
MySQL MongoDB 基础字段映射
MongoDB MySQL 基础字段映射

首期不实现实时 CDC、跨库事务、双向实时同步、任意脚本执行和自动删除目标数据。

2. 单包交付

项目只生成一个 syncdb 可执行文件,包含 REST API、MySQL/MongoDB 适配器、同步引擎、任务调度、审计模块和通过 go:embed 嵌入的 Vue 前端。运行时外部文件为 config.yamldata/syncdb.dblogs/

后端使用 Go net/http,不使用 Spring Boot。前端使用 Vue 3 + TypeScript,构建后的 web/dist 必须在 Go 编译前生成。

3. 系统架构

浏览器
  ↓ HTTP/REST + SSE
Go Web 服务
  ├── API 与鉴权
  ├── 数据源管理
  ├── MySQL Adapter
  ├── MongoDB Adapter
  ├── 结构检查与字段映射
  ├── 同步引擎
  ├── 任务调度与有限并发
  ├── 脱敏处理
  └── SQLite 元数据仓储

4. 核心功能

数据源管理

  • 创建、编辑、删除和测试 MySQL/MongoDB 连接。
  • 凭据加密保存,接口不得返回密码,日志不得输出密码或含凭据的 URI。
  • 数据源带开发、测试、生产环境标签;生产数据源默认禁止作为目标。

对象浏览与结构检查

MySQL 检查 database、table、column、primary key、unique key、index 和 foreign key。MongoDB 检查 database、collection、_id、index、collection options 和 JSON Schema validator。

MongoDB 文档结构使用采样推断,记录字段路径、类型和出现频率,并标记为“推断结构”;不得据此自动删除或修改目标结构。

数据同步

  • 支持全量、主键/_id 范围、时间字段增量和条件过滤。
  • 支持 Insert、Replace、Update、Upsert、Skip、Fail 冲突策略。
  • 支持分页读取、批量写入、最大行数、超时、取消和有限重试。
  • 默认只新增或更新,不自动删除目标记录;dry-run 不写目标库。
  • 长时间全量同步不使用显式事务包裹,减少锁持有时间。

跨数据库字段映射

支持字段重命名、嵌套字段路径、默认值、空值处理、忽略字段、JSON/数组转换和基础类型转换。

{"source":"users","target":"users","mapping":{"id":"_id","user_name":"profile.name","email":"email","created_at":"createdAt"}}

必须处理自增主键与 MongoDB _id、DECIMAL 精度、时区、NULL/字段缺失、数组/嵌套文档和 MySQL JSON。

Binlog 与已执行 SQL

仅针对 MySQL 数据源提供 Binlog 浏览能力,用于查看增量事件和定位同步问题。支持按数据源、时间范围、Binlog 文件、位置、数据库、表、事件类型和关键字筛选;详情展示时间、事务 ID、文件与位置、数据库/表、事件类型、主键和脱敏后的变更内容。默认只读,不支持 Web 修改、删除或重放 Binlog。

同步服务记录自己生成并执行的 SQL,形成可检索的 SQL 审计记录。记录任务、批次、目标数据源、起止时间、SQL 类型、影响行数、耗时、状态、错误信息和脱敏后的 SQL。敏感值不得原样保存;超长 SQL 保存摘要、哈希和可配置长度的预览。

建议接口:

GET /api/binlog/events
GET /api/binlog/events/{id}
GET /api/sql-executions
GET /api/sql-executions/{id}
GET /api/sql-executions/{id}/sql

读取 Binlog 需要 MySQL 复制读取权限,并设置文件大小、时间范围和查询频率限制,避免影响主库。syncdb 只保存查询索引和必要的脱敏事件摘要。

脱敏与执行

支持手机号、邮箱、姓名、身份证号等字段的掩码、哈希、随机替换、清空和截断。任务包含源/目标、对象、模式、过滤器、映射、脱敏规则、批次大小、冲突策略和计划。执行记录保存处理/成功/跳过/失败数量、错误信息和配置版本。

任务使用 goroutine 执行,但必须限制并发数,并支持超时、取消、有限重试和优雅关闭。前端使用 SSE 获取实时进度。

5.1 SQL 导出压缩包

针对 MySQL 数据源提供 SQL 导出功能,生成可下载的压缩包。支持仅结构、仅数据或结构加数据,支持指定表、过滤条件、分批导出和可选脱敏。服务端将压缩包写入临时制品目录并以流方式下载,避免把完整导出文件加载到内存。

压缩包内容建议为:

manifest.json
schema.sql        # 请求结构时生成
 data/
   users.sql
   orders.sql

大型导出必须拆分为大小受限的 SQL 文件。manifest.json 记录数据源类型、对象列表、导出选项、行数、校验和、创建时间和工具版本,不得记录凭据或未脱敏的敏感数据。

导出任务异步执行,并通过 SSE 推送进度。下载需要鉴权,文件名使用 syncdb-export-{id}.tar.gz,制品在可配置时间后过期并由清理任务删除。生产数据导出需要显式确认,默认启用脱敏。SQL 值必须使用安全转义,不得将不可信输入直接拼接到 SQL 语句中。

推荐接口:

POST   /api/exports/sql
GET    /api/exports
GET    /api/exports/{id}
GET    /api/exports/{id}/download
DELETE /api/exports/{id}
GET    /api/exports/{id}/events

5.1 复制账号权限向导

页面必须明确提示:主库只有 SELECT 的只读账号不足以完成从库同步。提供权限向导,生成可审核、可复制或下载的创建账号和删除账号 SQL,默认不自动执行。

账号分工:

syncdb_reader          主库:全量导出和元数据读取
syncdb_repl            主库:复制连接和 Binlog 读取
syncdb_replica_admin   从库:配置、启动、停止和查看复制
syncdb_applier         从库:可选,限制复制事务的应用权限

创建和删除 SQL 必须显示目标主机、数据库范围和风险提示;执行需要显式确认并写入审计日志。密码单独生成或输入,不写入文档和日志。

MySQL 8 示例模板:

-- 主库
CREATE USER 'syncdb_reader'@'syncdb_host' IDENTIFIED BY '<reader-password>';
GRANT SELECT, SHOW VIEW, TRIGGER, LOCK TABLES ON `app`.* TO 'syncdb_reader'@'syncdb_host';
CREATE USER 'syncdb_repl'@'replica_host' IDENTIFIED BY '<replication-password>';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'syncdb_repl'@'replica_host';

-- 从库
CREATE USER 'syncdb_replica_admin'@'syncdb_host' IDENTIFIED BY '<admin-password>';
GRANT REPLICATION SLAVE, REPLICATION CLIENT, CONNECTION_ADMIN ON *.* TO 'syncdb_replica_admin'@'syncdb_host';

删除模板:

-- 主库
DROP USER IF EXISTS 'syncdb_reader'@'syncdb_host';
DROP USER IF EXISTS 'syncdb_repl'@'replica_host';
-- 从库:停止复制并确认依赖后执行
DROP USER IF EXISTS 'syncdb_replica_admin'@'syncdb_host';
DROP USER IF EXISTS 'syncdb_applier'@'syncdb_host';

页面生成 SQL 前检查 MySQL 版本、主从角色、账号主机限制、现有用户和运行中的复制配置。不得建议删除仍被运行中的 Replica 使用的账号;复制权限和 syncdb_applier 的精确授权需根据版本和复制配置由 DBA 审核。

5. REST API

GET/POST/PUT/DELETE /api/datasources[/{id}]
POST /api/datasources/{id}/test
GET  /api/datasources/{id}/objects
POST /api/schema/diff | /api/schema/plan | /api/schema/apply
GET/POST/PUT/DELETE /api/tasks[/{id}]
POST /api/tasks/{id}/run | /api/tasks/{id}/cancel
GET /api/executions[/{id}]
GET /api/executions/{id}/errors | /api/executions/{id}/events
GET /api/health

6. 代码组织

cmd/syncdb/main.go
internal/api/ internal/config/ internal/datasource/
internal/adapter/mysql/ internal/adapter/mongo/
internal/syncengine/ internal/mapping/ internal/masking/
internal/task/ internal/execution/ internal/repository/
web/src/ web/dist/ web/embed.go migrations/

适配器统一实现连接测试、对象列表、对象检查、记录读取和批量写入接口;MySQL 表元数据与 MongoDB 集合元数据保持独立建模。

7. Drone CI/CD

流水线顺序:前端构建 web/distgo test ./... → 嵌入前端并交叉编译 → 生成压缩包 → 构建/推送 Docker 镜像。仅 Git tag(如 v1.0.0)发布正式版本。

建议使用 CGO_ENABLED=0-trimpath-ldflags="-s -w"。最终镜像只包含证书、时区数据和 syncdb 二进制。

8. 安全原则

  • 破坏性结构操作默认关闭,并需要单独确认。
  • 同步前检查连接、权限、目标对象、白名单和最大数据量。
  • 生产到非生产默认启用脱敏。
  • 失败时停止后续步骤并保存错误明细。
  • 审计数据源、任务、脱敏规则、执行和高风险确认操作。
  • 元数据默认使用 SQLite,未来可增加 MySQL 元数据库支持多实例。

9. 实施顺序

  1. 初始化 Go 服务、配置、SQLite 迁移和健康检查。
  2. 实现 MySQL/MongoDB 数据源管理与连接测试。
  3. 实现对象浏览、元数据检查和基础 API。
  4. 实现同类型全量同步、批量写入、Upsert、取消和进度记录。
  5. 实现跨数据库字段映射和类型转换。
  6. 实现脱敏、SSE、任务调度和审计。
  7. 完成 Vue 页面、go:embed 单包构建和 Drone CI 发布。