15.6 BLACKHOLE 存储引擎

BLACKHOLE存储引擎充当“黑洞”,它接受数据但将其丢弃并不进行存储。检索始终返回空结果:

mysql> CREATE TABLE test(i INT, c CHAR(10)) ENGINE = BLACKHOLE;
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM test;
Empty set (0.00 sec)

如果要从源代码构建 MySQL,则要启用BLACKHOLE存储引擎,请使用-DWITH_BLACKHOLE_STORAGE_ENGINE选项调用 CMake

要检查BLACKHOLE引擎的源,请查看 MySQL 源分发的sql目录。

创建BLACKHOLEtable 时,服务器将在数据库目录中创建 table 格式文件。该文件以 table 名开头,extensions 为.frm。没有与该 table 关联的其他文件。

BLACKHOLE存储引擎支持各种索引。也就是说,您可以在 table 定义中包括索引声明。

您可以使用SHOW ENGINES语句检查BLACKHOLE存储引擎是否可用。

插入到BLACKHOLEtable 中不会存储任何数据,但是如果启用了基于语句的二进制日志记录,则会记录 SQL 语句并将其复制到从属服务器。这可以用作转发器或过滤器机制。

假设您的应用程序需要从属端过滤规则,但是先将所有二进制日志数据传输到从属端会导致流量过多。在这种情况下,可以在主控主机上设置一个“虚拟”从属进程,其默认存储引擎为BLACKHOLE,如下所示:

图 15.1 使用 BLACKHOLE 进行过滤的复制

使用 BLACKHOLE 复制以进行过滤

主机写入其二进制日志。 “虚拟” mysqld进程充当从属,应用replicate-do-*replicate-ignore-*规则的所需组合,并编写自己的新的,经过过滤的二进制日志。 (请参见第 16.1.6 节“复制和二进制日志记录选项和变量”。)此筛选后的日志提供给从属服务器。

虚拟进程实际上并不存储任何数据,因此在复制主控主机上运行附加的mysqld进程几乎不会产生处理开销。可以使用其他复制从属来重复这种设置。

BLACKHOLE个 table 的INSERT个触发器按预期工作。但是,由于BLACKHOLEtable 实际上不存储任何数据,因此UPDATEDELETE触发器未激活:触发器定义中的FOR EACH ROW子句不适用,因为没有行。

BLACKHOLE存储引擎的其他可能用途包括:

  • 验证转储文件语法。

  • 通过比较在启用和未启用二进制日志记录的情况下使用BLACKHOLE的性能来衡量二进制日志记录的开销。

  • BLACKHOLE本质上是“无操作”存储引擎,因此可以用于查找与存储引擎本身无关的性能瓶颈。

BLACKHOLE引擎可识别事务,这意味着已提交的事务不会写入二进制日志,而回滚的事务不会。

黑洞引擎和自动增量列

黑洞引擎是无操作引擎。使用 Blackhole 在 table 上执行的任何操作均无效。在考虑自动递增的主键列的行为时应牢记这一点。引擎将不会自动增加字段值,并且不会保留自动增加字段状态。这在复制中具有重要意义。

请考虑以下所有三种情况都适用的复制方案:

  • 在主服务器上,存在一个黑洞 table,该 table 具有作为主键的自动增量字段。

  • 在从属服务器上,存在相同的 table,但使用 MyISAM 引擎。

  • 无需在INSERT语句本身或使用SET INSERT_ID语句中显式设置自动增量值的情况下,即可执行插入到主 table 的操作。

在这种情况下复制将失败,并在主键列上出现重复的 Importing 错误。

在基于语句的复制中,上下文事件中的INSERT_ID的值将始终相同。因此,由于尝试为主键列插入具有重复值的行而导致复制失败。

在基于行的复制中,引擎为该行返回的值对于每个插入始终是相同的。这将导致从服务器尝试使用主键列的相同值重播两个插入日志条目,因此复制将失败。

Column Filtering

使用基于行的复制(binlog_format=ROW)时,如 table第 16.4.1.10 节,“在源和副本上使用不同的 table 定义进行复制”所述,支持从 table 中缺少最后一列的从属服务器。

此过滤在从属端进行,也就是说,在将列过滤掉之前,会将列复制到从属。至少有两种情况不希望将列复制到从属服务器:

  • 如果数据是机密的,则从属服务器不应有权访问它。

  • 如果主节点有许多从节点,则在发送到从节点之前进行过滤可能会减少网络流量。

使用BLACKHOLE引擎可以实现主列过滤。通过使用BLACKHOLE引擎和--replicate-do-table--replicate-ignore-table选项,以类似于实现主 table 筛选的方式执行此操作。

主机的设置为:

CREATE TABLE t1 (public_col_1, ..., public_col_N,
                 secret_col_1, ..., secret_col_M) ENGINE=MyISAM;

可信从站的设置为:

CREATE TABLE t1 (public_col_1, ..., public_col_N) ENGINE=BLACKHOLE;

不受信任的从站的设置为:

CREATE TABLE t1 (public_col_1, ..., public_col_N) ENGINE=MyISAM;