# 16.6 黑洞存储引擎

黑洞存储引擎充当“黑洞”,接受数据但将其丢弃而不存储。检索总是返回空结果:

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,调用制作-DWITH_BLACKHOLE_STORAGE_ENGINE选项。

检查源黑洞发动机,看看sqlMySQL 源代码分发的目录。

当你创建一个黑洞表,服务器在全局数据字典中创建表定义。没有与该表关联的文件。

黑洞存储引擎支持各种索引。也就是说,您可以在表定义中包含索引声明。

从 MySQL 8.0.27 开始,最大密钥长度为 3072 字节。在 8.0.27 之前,最大密钥长度为 1000 字节。

黑洞存储引擎不支持分区。

您可以检查是否黑洞存储引擎可与显示引擎陈述。

插入一个黑洞table 不存储任何数据,但如果启用了基于语句的二进制日志记录,则会记录 SQL 语句并将其复制到副本服务器。这可用作中继器或过滤器机制。

假设您的应用程序需要副本端过滤规则,但首先将所有二进制日志数据传输到副本会导致流量过多。在这种情况下,可以在复制源服务器上设置一个“虚拟”副本进程,其默认存储引擎为黑洞,描绘如下:

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

The replication source server uses a source mysqld process and a dummy mysqld process. On the replica, the mysqld process replicates from the dummy mysqld process.

源写入其二进制日志。“假人”mysqld过程充当复制品,应用所需的组合复制做-*复制忽略-*规则,并写入自己的新过滤二进制日志。(看第 17.1.6 节,“复制和二进制日志记录选项和变量”.) 此过滤后的日志提供给副本。

虚拟进程实际上并不存储任何数据,因此运行附加进程所产生的处理开销很小mysqld复制源服务器上的进程。可以使用其他副本重复这种类型的设置。

插入触发黑洞表按预期工作。然而,由于黑洞表实际上并不存储任何数据,更新删除触发器未激活:每一行触发器定义中的子句不适用,因为没有行。

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

  • 验证转储文件语法。

  • 通过比较性能来测量二进制日志记录的开销黑洞启用和不启用二进制日志记录。

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

    黑洞引擎是事务感知的,从某种意义上说,已提交的事务被写入二进制日志,而回滚事务则没有。

黑洞引擎和自动增量列

黑洞引擎是无操作引擎。使用对表执行的任何操作黑洞没有效果。在考虑自动递增的主键列的行为时,应牢记这一点。引擎不会自动递增字段值,也不会保留自动递增字段状态。这对复制具有重要意义。

考虑以下所有三个条件都适用的复制场景:

  1. 在源服务器上,有一个黑洞表,其中包含一个作为主键的自动增量字段。

  2. 在副本上存在同一个表,但使用的是 MyISAM 引擎。

  3. 插入是在源表中执行的,而无需在插入声明本身或通过使用设置 INSERT_ID陈述。

    在这种情况下,复制失败,主键列出现重复条目​​错误。

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

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

列过滤

使用基于行的复制时,(binlog_format=行),支持表中缺少最后一列的副本,如 部分所述第 17.5.1.9 节,“在源和副本上具有不同表定义的复制”.

此过滤在副本端起作用,即列在被过滤掉之前被复制到副本中。至少有两种情况不希望将列复制到副本:

  1. 如果数据是机密的,那么副本服务器应该无权访问它。

  2. 如果源有许多副本,则在发送到副本之前进行过滤可能会减少网络流量。

    源列过滤可以使用黑洞引擎。这以类似于实现源表过滤的方式执行 - 通过使用黑洞发动机和--replicate-do-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;