jackiesre721/mydml
GitHub: jackiesre721/mydml
一个基于主键范围的安全MySQL批量DML工具,带有节流和复制延迟控制。
Stars: 0 | Forks: 0
# mydml
[](https://pkg.go.dev/github.com/jackiesre721/mydml)
[](https://goreportcard.com/report/github.com/jackiesre721/mydml)
[](https://opensource.org/licenses/MIT)
[](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, 开发工具, 批量操作, 数据库, 数据库维护, 数据迁移, 无依赖, 无锁, 日志审计, 最大行数限制, 服务器负载, 程序破解, 空运行模式, 自定义查询, 自适应限流, 触发器, 运维工具, 限流, 预检查