jackiesre721/mydml

GitHub: jackiesre721/mydml

一个基于主键范围的安全MySQL批量DML工具,带有节流和复制延迟控制。

Stars: 0 | Forks: 0

# mydml [![Go 参考](https://pkg.go.dev/badge/github.com/jackiesre721/mydml.svg)](https://pkg.go.dev/github.com/jackiesre721/mydml) [![Go 报告卡](https://goreportcard.com/badge/github.com/jackiesre721/mydml)](https://goreportcard.com/report/github.com/jackiesre721/mydml) [![许可证: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/7cb9dc74d2045252.svg)](https://github.com/jackiesre721/mydml/actions/workflows/ci.yml) **MySQL 大规模 DML 工具 — 无锁执行批量 DELETE / UPDATE / INSERT_SELECT。** [中文文档](README_zh.md) ## 功能 - 按**主键范围**(而非 OFFSET)将 DML 拆分为小批次 - 三种模式:**DELETE**、**UPDATE**、**INSERT_SELECT** - **自适应限流** — 基于复制延迟、服务器负载、自定义查询 - **HTTP 控制 API** — 运行时暂停 / 恢复 / 停止 - **模拟运行**模式和**最大行数**限制 - 预检查:binlog 格式、外键、触发器 - 单 Go 二进制文件,无外部依赖 ## 安装 **一键安装(macOS / Linux):** ``` curl -fsSL https://github.com/jackiesre721/mydml/raw/main/install.sh | bash ``` **macOS (Homebrew):** ``` brew install jackiesre721/tap/mydml ``` **Linux (deb/rpm):** ``` # Debian/Ubuntu wget https://github.com/jackiesre721/mydml/releases/latest/download/mydml_amd64.deb sudo dpkg -i mydml_amd64.deb # RHEL/CentOS/Fedora sudo rpm -i https://github.com/jackiesre721/mydml/releases/latest/download/mydml_amd64.rpm ``` **Go install:** ``` go install github.com/jackiesre721/mydml/cmd/mydml@latest ``` 或者从源码构建: ``` git clone https://github.com/jackiesre721/mydml.git cd mydml make build ``` ## 快速上手 ### 删除行 ``` mydml delete \ --host=127.0.0.1 --port=3306 \ --user=root --password=secret \ --database=mydb \ --table=orders \ --where="status = 'expired' AND created_at < '2024-01-01'" \ --batch-size=500 --sleep-ms=100 ``` ### 更新行 ``` mydml update \ --host=127.0.0.1 --port=3306 \ --user=root --password=secret \ --database=mydb \ --table=orders \ --where="status = 'pending' AND created_at < '2023-01-01'" \ --set="status = 'archived'" \ --batch-size=500 --sleep-ms=100 ``` ### 插入-选择(数据迁移) ``` mydml insert-select \ --host=127.0.0.1 --port=3306 \ --user=root --password=secret \ --database=mydb \ --source-table=orders \ --target-table=orders_archive \ --where="created_at < '2023-01-01'" \ --batch-size=500 --sleep-ms=100 ``` ### 模拟运行(仅计数,不修改数据) ``` mydml delete \ --host=127.0.0.1 --user=root --database=mydb \ --table=orders \ --where="status = 'expired'" \ --dry-run ``` ## 全部参数 | 参数 | 默认值 | 描述 | |------|---------|-------------| | `--host` | `127.0.0.1` | MySQL 主机 | | `--port` | `3306` | MySQL 端口 | | `--user` | | MySQL 用户(必填) | | `--password` | | MySQL 密码 | | `--database` | | MySQL 数据库(必填) | | `--table` | | 目标表(DELETE/UPDATE 时必填) | | `--where` | | WHERE 条件(不含 `WHERE` 关键字)(必填) | | `--set` | | UPDATE 模式的 SET 子句(UPDATE 时必填) | | `--source-table` | | INSERT_SELECT 的源表(必填) | | `--target-table` | | INSERT_SELECT 的目标表(必填) | | `--columns` | | INSERT_SELECT 的列列表(默认:`*`) | | `--batch-size` | `500` | 每批行数(100–5000) | | `--sleep-ms` | `100` | 批次间基础休眠时间(毫秒) | | `--max-lag-sec` | `1` | 最大复制延迟阈值(秒) | | `--nice-ratio` | `0` | 工作:休眠比率(0=固定休眠,>0=按比例) | | `--max-load` | | 负载阈值,例如 `Threads_running=25` | | `--critical-load` | | 临界负载阈值(超过则停止任务) | | `--throttle-query` | | 用于限流检查的自定义 SQL(值 > 0 触发限流) | | `--check-slave-lag` | | 用于延迟检查的副本 `host:port`(可重复) | | `--dry-run` | `false` | 模拟运行模式(仅计数,不修改数据) | | `--max-rows` | `0` | 最大影响行数(0=无限制) | | `--control-addr` | `127.0.0.1:8080` | HTTP 控制 API 地址 | | `--task-id` | | 自定义任务 ID(留空则自动生成) | | `--verbose` | `false` | 详细日志 | | `--log-file` | | 日志文件路径(默认:标准输出) | 环境变量:`MYSQL_DELETE_HOST`、`MYSQL_DELETE_PORT`、`MYSQL_DELETE_USER`、`MYSQL_DELETE_PASSWORD`、`MYSQL_DELETE_DATABASE`、`MYSQL_DELETE_TABLE`。 ## HTTP 控制 API 当任务运行时,您可以通过 HTTP 控制它: ``` # 暂停 curl -X POST http://127.0.0.1:8080/api/v1/pause # 恢复 curl -X POST http://127.0.0.1:8080/api/v1/resume # 停止(完成当前批次后退出) curl -X POST http://127.0.0.1:8080/api/v1/stop # 立即终止 curl -X POST http://127.0.0.1:8080/api/v1/panic # 状态 curl http://127.0.0.1:8080/api/v1/status # 运行时调整节流 curl -X PUT http://127.0.0.1:8080/api/v1/config \ -d '{"sleep_ms": 200, "nice_ratio": 1.5, "max_lag_sec": 5}' ``` ## 工作原理 ``` 1. Validate config & connect to MySQL 2. Pre-flight checks (binlog format, foreign keys, triggers) 3. Detect PK column from information_schema - Must be single-column integer PK 4. Get PK range: SELECT pk FROM t ORDER BY pk ASC LIMIT 1 -- min SELECT pk FROM t ORDER BY pk DESC LIMIT 1 -- max 5. Execute in batches (one of three modes): DELETE mode: DELETE FROM t WHERE pk >= cursor AND pk < cursor + batch_size AND status = 'expired' UPDATE mode: UPDATE t SET status = 'archived' WHERE pk >= cursor AND pk < cursor + batch_size AND status = 'expired' INSERT_SELECT mode: INSERT INTO target SELECT * FROM source WHERE pk >= cursor AND pk < cursor + batch_size AND created_at < '2023-01-01' 6. Throttle: sleep based on affected rows, replication lag, server load, and nice-ratio 7. Report summary when done ``` **关键设计选择:** - **主键范围批处理**(而非 OFFSET)— 避免表扫描和锁升级 - **ORDER BY + LIMIT 1** 获取主键范围 — B+树直接访问叶节点,O(log n),在十亿行表上性能良好 - **主键范围约束批次大小** — 每个分块恰好覆盖 `batch_size` 个主键值,无需 LIMIT - **自适应限流** — 当复制延迟、锁等待或服务器负载超过阈值时,增加休眠时间 ## 要求 - MySQL 5.7+ 或兼容版本(MariaDB、TiDB 等) - 目标表必须有**单列整型主键**(BIGINT、INT 等) - `binlog_format` 必须是 ROW 或 MIXED(STATEMENT 会被拒绝) - 表不能被子表的外键引用 ## 限制 - 不支持复合主键 - 不支持非整型(VARCHAR、DATETIME)主键 - 不支持检查点/恢复 — 如果中断,工具将从头重新启动(但已处理的行会被简单跳过,因为它们不再满足 WHERE 条件) - 控制 API 无身份验证(默认绑定到 localhost) ## 许可证 [MIT](LICENSE)
标签:binlog格式, DELETE操作, DML工具, EVTX分析, Go语言, HTTP控制API, INSERT_SELECT操作, SOC Prime, UPDATE操作, 主键范围, 单二进制, 复制延迟控制, 外键, 安全DML, 开发工具, 批量操作, 数据库, 数据库维护, 数据迁移, 无依赖, 无锁, 日志审计, 最大行数限制, 服务器负载, 程序破解, 空运行模式, 自定义查询, 自适应限流, 触发器, 运维工具, 限流, 预检查