当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL BLACKHOLE 存储引擎适合什么复制中转场景

MySQL BLACKHOLE 存储引擎适合什么复制中转场景

来源:17golang原创 2026-11-11 04:10:36 0浏览 收藏

如果你把 MySQL BLACKHOLE 当成普通业务表,最容易得到两个错误结论:一是以为插入成功就能再查出来,二是以为没有表数据就不会参与复制。它真正适合的是“让一个中转 mysqld 进程接收并过滤复制事件,再把新的二进制日志交给下游副本”的架构。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/blackhole-storage-engine.html

BLACKHOLE 表本身不落盘,读取总是空结果;但在启用 statement-based binary logging 时,写入语句仍可以进入二进制日志并复制到下游。因此它更像复制链路中的“无数据中转层”,而不是缓存、归档表或业务存储。下面按实际决策顺序说明它适合什么场景,以及上线前需要避开的边界。

先确认 BLACKHOLE 的读写语义

先把表的两个事实分开:表数据不保存,复制日志可以保存事件。官方文档给出的行为是,INSERT 能返回成功,但随后执行 SELECT 不会得到刚才写入的行。这个特征正是它能做中转节点的原因,也是它不能替代 InnoDB 的原因。

-- 创建一个只保留表定义、不保留行数据的表
CREATE TABLE relay_events (
    event_id BIGINT NOT NULL,
    payload  VARBINARY(1024) NOT NULL,
    PRIMARY KEY (event_id)
) ENGINE = BLACKHOLE;

-- 写入语句可以成功,但 BLACKHOLE 不保存行
INSERT INTO relay_events(event_id, payload)
VALUES (1001, X'010203');

-- 查询不会返回上面插入的记录
SELECT event_id, payload
FROM relay_events;

这里的“成功”只表示服务器接受了写入操作,不表示数据已经落在某个可查询的数据页中。即使表定义里声明了索引,也不能把索引当作可供查询的持久化数据结构。需要重放、查询、补偿或审计原始行时,应使用真正保存数据的引擎。

BLACKHOLE 表的 INSERT、SELECT 和 binary log 静态关系说明图
图1:BLACKHOLE 写入、读取与日志语义说明图,区分表数据不保存和复制日志可继续传播;这是静态说明图,不是运行截图。

把 BLACKHOLE 放进复制过滤链路

最典型的架构不是“业务应用直接连 BLACKHOLE”,而是在复制源旁边运行一个 dummy mysqld。源服务器先写自己的二进制日志,dummy mysqld 作为副本接收事件,再依据 replicate-do-* 或 replicate-ignore-* 规则应用需要的过滤,最后由这个中转进程写出新的二进制日志,供下游副本继续复制。

-- 下面是中转实例上的过滤意图示例;实际参数应写入该实例的启动配置
-- 只让指定业务库进入中转实例的复制链路
replicate-do-db=orders

-- 对不需要下发的表进行过滤,避免把无关事件交给下游
replicate-ignore-table=orders.tmp_import

-- 中转实例上的业务表使用 BLACKHOLE,表定义仍需与复制规则匹配
CREATE TABLE orders.order_events (
    id BIGINT NOT NULL,
    event_type VARCHAR(64) NOT NULL,
    created_at TIMESTAMP NOT NULL
) ENGINE = BLACKHOLE;

这个方案的价值是把过滤动作提前到靠近源端的位置:下游副本不必先接收所有二进制日志再丢弃,多个副本还可以复用同一个过滤后的日志出口。BLACKHOLE 负责“不保存表行”,dummy mysqld 负责“接收、过滤并重新产生日志”,两者不要混为一个概念。

源 MySQL、BLACKHOLE 中转节点和下游副本的复制过滤架构说明图
图2:BLACKHOLE 复制中转架构说明图,强调过滤规则位于中转 mysqld,连线表达静态架构关系,不是运行截图。

哪些复制中转场景适合使用

可以用下面的判断表快速缩小范围:

场景是否适合原因
源端先过滤,再给多个下游副本适合中转实例可以生成过滤后的二进制日志,减少下游接收无关事件。
只测量二进制日志和复制开销适合存储引擎不落盘,便于把存储层开销从测量目标中剥离。
临时验证 dump 文件中的 SQL 语法适合可以接受写入而不保留数据,适合做语句层面的检查。
需要查询、补偿或恢复业务数据不适合写入不会留下可读取的行,无法承担数据恢复职责。
依赖 UPDATE/DELETE 行触发器不适合BLACKHOLE 没有实际行,UPDATE 和 DELETE 的行级触发器不会按普通表工作。

所以,标题中的“中转”必须指复制日志的中转,而不是业务数据的中转。若下游需要完整的行数据,应该让过滤后的事件落到合适的持久化引擎,再由下游消费。

上线前要避开的复制边界

自增列不能按普通表理解

BLACKHOLE 是 no-op 引擎,不会自动维护自增值,也不保留自增状态。如果源端的 BLACKHOLE 表依赖自增主键,而下游表使用 MyISAM 等实际存储引擎,且 INSERT 没有显式设置自增值,复制可能因为重复主键而失败。中转表最好使用业务侧明确生成的主键,或者在复制协议中明确处理 INSERT_ID,不要把自增状态交给 BLACKHOLE。

-- 中转表显式接收业务生成的唯一 ID,避免依赖 BLACKHOLE 的自增状态
CREATE TABLE relay_events (
    event_id BIGINT NOT NULL,
    body     VARBINARY(2048) NOT NULL,
    PRIMARY KEY (event_id)
) ENGINE = BLACKHOLE;

-- 写入时由上游明确提供 ID,复制两端看到的键保持一致
INSERT INTO relay_events(event_id, body)
VALUES (9000001, X'0A0B0C');

触发器和表结构差异要单独评估

BLACKHOLE 表上的 INSERT 触发器可以按预期工作,但 UPDATE 和 DELETE 触发器依赖实际行,不能按普通 InnoDB 表推断。使用 row-based replication 时,列过滤也有明确边界:源端可以先准备公开列和敏感列,中转或可信副本使用不同的表定义配合过滤规则。这个设计需要把表结构、binlog_format 和复制选项一起审阅,不能只改 ENGINE。

一份可执行的落地清单

  1. 先执行 SHOW ENGINES,确认当前实例的 BLACKHOLE 状态可用,再决定是否部署中转实例。
  2. 把中转实例和业务源实例分开看:前者负责复制接收、过滤和日志输出,后者负责真实业务数据。
  3. 逐张核对中转表定义,尤其是主键、自增列、触发器、列顺序和下游表引擎。
  4. 明确复制格式与过滤参数,记录哪些库表会进入中转日志,哪些事件会在源端被排除。
  5. 把“查询为空”写进运维说明和告警判断,避免值班人员把它误判成复制延迟或数据丢失。
-- 上线前快速确认存储引擎是否被当前实例启用
SHOW ENGINES;

-- 只检查表定义,不把空查询误认为表不可用
SHOW CREATE TABLE relay_events;

最终可以这样做选择:如果目标是靠近源端过滤复制事件、减少下游无关日志,BLACKHOLE 适合做轻量中转;如果目标是保存、查询或恢复数据,就应选择真正持久化的存储引擎。它的优势来自“不保存”,风险也恰恰来自“不保存”。

相关问题

BLACKHOLE 表为什么 INSERT 成功后 SELECT 为空?

因为它接受写入后直接丢弃行数据,查询没有可读取的记录;成功不等于保存。

BLACKHOLE 能不能当临时缓存表?

不能。它没有可供后续读取的行,也不保留自增状态,不具备缓存表的基本语义。

为什么 BLACKHOLE 还能参与复制?

在适用的二进制日志配置下,写入语句仍可以进入 binary log;复制链路传播的是日志事件,不是 BLACKHOLE 表里已经保存的行。

复制中转表应该使用自增主键吗?

不建议把主键生成依赖 BLACKHOLE 的自增状态。更稳妥的方式是由上游明确生成并写入唯一 ID,再让复制两端保持一致。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MySQL BIT_COUNT 怎么统计位标志中被置为 1 的数量MySQL BIT_COUNT 怎么统计位标志中被置为 1 的数量
上一篇
MySQL BIT_COUNT 怎么统计位标志中被置为 1 的数量
MySQL C API 读取含零字节字段时怎么使用 mysql_fetch_lengths
下一篇
MySQL C API 读取含零字节字段时怎么使用 mysql_fetch_lengths
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    974次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    980次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1096次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1068次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    906次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码