这是 2020 年 7 月整理的 Maxwell 笔记。彼时 Maxwell 是轻量级的 MySQL binlog 解析工具(
zendesk/maxwell镜像),常与 Kafka 配合做 CDC 数据同步。本文聚焦它最实用的功能之一:存量数据初始化(bootstrap)。
⚠️ 项目状态说明(2026 年补充)
Maxwell(zendesk/maxwell)已于 2021 年底停止维护,GitHub 仓库已归档为只读状态。本文保留作为历史参考。
当前推荐替代方案:
- Debezium(首选):Kafka Connect 生态,社区活跃,支持 MySQL/PostgreSQL/MongoDB 等
- Canal(阿里开源):纯 MySQL binlog 订阅,国内生态成熟
- maxwell-plus:社区 fork,仍在维护,API 与 maxwell 兼容
本文的 bootstrap 概念、sync/async 模式、三阶段流程等知识对理解同类工具(特别是 maxwell-plus)依然有效。
Maxwell 与数据初始化
Maxwell 通过解析 MySQL 的 binlog 实现数据同步,天然只能拿到增量数据——binlog 里根本没有历史数据。
所以当我们需要把一张表已有的全量数据同步过去时,就需要 maxwell-bootstrap:
- 基于
SELECT * FROM table的方式做全量数据初始化。 - 不会产生多余的 binlog(全量是直读表,不是写 MySQL)。
maxwell-bootstrap 命令参数
docker run -it --rm zendesk/maxwell bin/maxwell-bootstrap \
--user maxwell \
--password 123456 \
--host 10.100.97.246 \
--database test \
--table test \
--client_id maxwell
| 参数 | 说明 |
|---|---|
--user / --password | MySQL 连接账号密码(需要 binlog 与 REPLICATION 相关权限) |
--host / --port | MySQL 地址与端口(默认 3306) |
--database | 需要初始化的库 |
--table | 需要初始化的表 |
--client_id | 客户端 ID,需与 Maxwell 主进程的 client_id 一致 |
--bootstrapper | 初始化模式:sync(同步)/ async(异步) |
--where | 可选,只初始化符合条件的行(SELECT * FROM table WHERE ...) |
--output_file | 可选,把 bootstrap 数据输出到文件而不是 Kafka |
--schema_database | 元数据库名(默认 maxwell) |
--where很有用:全表太大时可以先按条件分批初始化,例如按id分段。
实验:初始化 test 库的 test 表
1. 准备测试数据
在 MySQL 中创建 test 表并插入 4 条数据:
INSERT INTO `test` VALUES (1, 1, '1');
INSERT INTO `test` VALUES (2, 2, '2');
INSERT INTO `test` VALUES (3, 3, '3');
INSERT INTO `test` VALUES (4, 4, '4');
2. 清空 binlog 与环境
RESET MASTER; -- 清空 binlog,便于观察
-- 删除 maxwell 库中的表(清理上次实验的元数据)
DROP DATABASE IF EXISTS maxwell;
3. 启动 Kafka、Maxwell 和 Kafka 消费者
按 Maxwell 快速开始的命令启动:
# 启动 Kafka(假设已在本地/容器中)
# 启动 Maxwell(监听 binlog,把变更发到 Kafka)
docker run -it --rm zendesk/maxwell bin/maxwell \
--user maxwell --password 123456 \
--host 10.100.97.246 \
--producer kafka \
--kafka.bootstrap.servers localhost:9092 \
--kafka_topic maxwell
# 启动 Kafka 消费者(消费 maxwell topic,观察输出)
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic maxwell --from-beginning
4. 启动 maxwell-bootstrap
docker run -it --rm zendesk/maxwell bin/maxwell-bootstrap \
--user maxwell \
--password 123456 \
--host 10.100.97.246 \
--database test \
--table test \
--client_id maxwell
消费者端会收到 4 条 test.test 的数据,注意它们的 type 是 bootstrap-insert,而不是平时的 insert:
{"database":"test","table":"test","type":"bootstrap-insert","ts":1596000000,
"data":{"id":1,"a":1,"b":"1"}}
{"database":"test","table":"test","type":"bootstrap-insert","ts":1596000000,
"data":{"id":2,"a":2,"b":"2"}}
{"database":"test","table":"test","type":"bootstrap-insert","ts":1596000000,
"data":{"id":3,"a":3,"b":"3"}}
{"database":"test","table":"test","type":"bootstrap-insert","ts":1596000000,
"data":{"id":4,"a":4,"b":"4"}}
5. 验证不产生多余 binlog
再次查看 binlog:
SHOW BINLOG EVENTS;
会发现只有与 maxwell 相关的 binlog,并没有 test.test 相关的 binlog——证明 maxwell-bootstrap 不会产生多余的 binlog。当数据表的数量很大时,这个好处会更加明显(bootstrap 不写 MySQL,就不产生 binlog 放大)。
Bootstrap 的三个阶段
一次完整的 bootstrap 在 Kafka 中会依次出现三种事件:
bootstrap-start (开始,data 为空,不携带数据)
↓
bootstrap-insert (全量数据行,每行一条)
↓
bootstrap-complete (结束,data 为空,不携带数据)
// bootstrap-start:data 为空
{"database":"test","table":"test","type":"bootstrap-start","ts":1596000000,"data":{}}
// bootstrap-complete:data 为空
{"database":"test","table":"test","type":"bootstrap-complete","ts":1596000000,"data":{}}
消费端可以通过这三种事件类型识别一次完整的初始化过程,在 bootstrap-complete 时标记该表初始化完成。
sync 与 async 模式
| 模式 | 行为 | 适用场景 |
|---|---|---|
sync | 处理 bootstrap 时阻塞正常的 binlog 解析 | 数据量小、可接受短暂阻塞 |
async | 不阻塞 binlog 解析,后台异步执行 | 数据量大、要求实时同步不中断 |
# 显式指定 async 模式
docker run -it --rm zendesk/maxwell bin/maxwell-bootstrap \
--user maxwell --password 123456 --host 10.100.97.246 \
--database test --table test --client_id maxwell \
--bootstrapper async
用
sync模式时,bootstrap 期间的新增变更会排队等待,完成后继续处理;async模式下两边互不干扰,但要注意 bootstrap 与实时 binlog 的先后顺序由客户端自行判断。
手动触发 bootstrap
除了命令行工具,也可以在 Maxwell 元数据库的 maxwell.bootstrap 表中插入记录手动触发:
INSERT INTO maxwell.bootstrap (database_name, table_name)
VALUES ('test', 'test');
Maxwell 会定期扫描该表,发现有未处理的初始化任务就执行。适合程序化批量触发的场景。
崩溃恢复
在 bootstrap 过程中如果 Maxwell 崩溃,重启时 bootstrap 会完全重新开始,不管之前进行到多少。
若不希望重头再来,可以到数据库中手动处理:
-- 方式一:标记为已完成(跳过该行)
UPDATE maxwell.bootstrap SET is_complete = 1
WHERE database_name = 'test' AND table_name = 'test';
-- 方式二:直接删除该行(放弃初始化)
DELETE FROM maxwell.bootstrap
WHERE database_name = 'test' AND table_name = 'test';
is_complete = 1表示该表初始化已完成,重启后不会再触发;删除该行则彻底取消这个任务。
小结
- maxwell-bootstrap 基于
SELECT * FROM table做全量初始化,不产生多余 binlog。 - 参数:
--database/--table必填,--client_id需与主进程一致,--where可按条件分批。 - 三阶段事件:
bootstrap-start→bootstrap-insert→bootstrap-complete,start/complete 的 data 为空。 sync阻塞 binlog 解析、async不阻塞,大数据量推荐async。- 可写入
maxwell.bootstrap表手动触发。 - 崩溃后默认从头开始;用
is_complete = 1或删行可跳过/取消。