BLACKHOLE
El motor BLACKHOLE es posiblemente el más curioso de todos los motores de almacenamiento de MySQL. Acepta cualquier operación de escritura, la valida sintácticamente, pero no almacena absolutamente nada. Cualquier dato que insertes desaparece inmediatamente, como si cayera en un agujero negro. Las consultas SELECT siempre devuelven un conjunto vacío porque no hay datos que leer.
A primera vista, un motor que descarta todos los datos parece inútil. Sin embargo, BLACKHOLE tiene casos de uso legítimos en arquitecturas de replicación, pruebas de rendimiento y validación de esquemas. Su principal valor reside en que, aunque no almacena datos, sí escribe en el log binario de MySQL, lo que permite su uso como intermediario en topologías de replicación.
Sintaxis
Para crear una tabla con el motor BLACKHOLE:
CREATE TABLE nombre_tabla (
columna1 tipo_dato,
columna2 tipo_dato
) ENGINE = BLACKHOLE;Comportamiento básico
Cuando ejecutas un INSERT en una tabla BLACKHOLE, MySQL acepta la sentencia, la valida sintácticamente, verifica las restricciones de la tabla, pero no almacena ningún dato. La operación se reporta como exitosa.
CREATE TABLE datos_descartados (
id INT AUTO_INCREMENT PRIMARY KEY,
mensaje VARCHAR(200) NOT NULL,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE = BLACKHOLE;
INSERT INTO datos_descartados (mensaje) VALUES ('Este mensaje desaparecerá');
-- Query OK, 1 row affected (0.00 sec)A pesar del mensaje de éxito, la tabla está vacía:
SELECT * FROM datos_descartados;La consulta devuelve cero filas. El INSERT fue procesado y validado, pero el dato fue descartado antes de ser almacenado.
Las operaciones de UPDATE y DELETE también se aceptan sin error pero no tienen efecto real:
UPDATE datos_descartados SET mensaje = 'nuevo' WHERE id = 1;
-- Query OK, 0 rows affected
DELETE FROM datos_descartados WHERE id = 1;
-- Query OK, 0 rows affectedCaso práctico: filtrado en replicación
El caso de uso más importante de BLACKHOLE es su papel en topologías de replicación de MySQL. Cuando tienes un servidor maestro que genera un log binario con todas las operaciones, puedes usar un servidor intermedio con tablas BLACKHOLE como filtro de replicación.
Imagina que tienes un maestro con múltiples bases de datos pero solo quieres replicar una de ellas a un esclavo específico. En lugar de filtrar directamente en el esclavo, lo cual tiene limitaciones, puedes crear un servidor intermedio de filtrado:
-- En el servidor intermedio de filtrado
-- Solo la base de datos 'ventas' se replica hacia adelante
-- Las tablas de 'ventas' se crean como BLACKHOLE
CREATE TABLE ventas.pedidos (
id INT PRIMARY KEY,
cliente_id INT,
total DECIMAL(10,2)
) ENGINE = BLACKHOLE;El servidor intermedio recibe todas las operaciones del maestro, las escribe en su propio log binario (porque BLACKHOLE sí genera eventos de binlog) y las descarta sin consumir espacio en disco. Los esclavos finales se conectan a este servidor intermedio y reciben solo los eventos filtrados.
Esta arquitectura es especialmente útil cuando tienes múltiples esclavos que necesitan diferentes subconjuntos de datos del mismo maestro.
Caso práctico: medición de rendimiento
BLACKHOLE es una herramienta útil para medir el overhead de diferentes componentes del sistema. Al eliminar el almacenamiento de la ecuación, puedes aislar y medir el coste del procesamiento de consultas, la red y la validación de datos.
-- Crear la misma tabla con diferentes motores para comparar
CREATE TABLE bench_innodb (
id INT AUTO_INCREMENT PRIMARY KEY,
dato VARCHAR(200),
valor DECIMAL(10,2),
timestamp DATETIME
) ENGINE = InnoDB;
CREATE TABLE bench_blackhole (
id INT AUTO_INCREMENT PRIMARY KEY,
dato VARCHAR(200),
valor DECIMAL(10,2),
timestamp DATETIME
) ENGINE = BLACKHOLE;Al ejecutar la misma carga de inserciones masivas contra ambas tablas y comparar los tiempos, la diferencia representa el coste puro del almacenamiento en disco:
-- Medir el tiempo de inserción en InnoDB
INSERT INTO bench_innodb (dato, valor, timestamp)
SELECT CONCAT('registro_', seq), RAND() * 1000, NOW()
FROM (SELECT @rownum := @rownum + 1 AS seq
FROM information_schema.columns a,
information_schema.columns b,
(SELECT @rownum := 0) r
LIMIT 100000) nums;
-- Tiempo: 4.52 sec (ejemplo)
-- Medir el tiempo de inserción en BLACKHOLE
INSERT INTO bench_blackhole (dato, valor, timestamp)
SELECT CONCAT('registro_', seq), RAND() * 1000, NOW()
FROM (SELECT @rownum := @rownum + 1 AS seq
FROM information_schema.columns a,
information_schema.columns b,
(SELECT @rownum := 0) r
LIMIT 100000) nums;
-- Tiempo: 0.38 sec (ejemplo)La diferencia de tiempo entre ambas operaciones indica cuánto tiempo se invierte en las operaciones de E/S de disco y gestión del buffer pool. Esto te permite determinar si el cuello de botella de tu aplicación está en el procesamiento SQL o en el almacenamiento.
Caso práctico: validación y prueba de triggers
Otro uso práctico de BLACKHOLE es probar triggers sin afectar datos reales. Si tienes un trigger complejo que quieres depurar, puedes crear una tabla BLACKHOLE con la misma estructura y asociar el trigger a ella:
CREATE TABLE test_trigger (
id INT AUTO_INCREMENT PRIMARY KEY,
producto_id INT NOT NULL,
cantidad INT NOT NULL,
tipo ENUM('entrada', 'salida') NOT NULL
) ENGINE = BLACKHOLE;
CREATE TABLE log_trigger (
id INT AUTO_INCREMENT PRIMARY KEY,
mensaje VARCHAR(500),
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE = InnoDB;
DELIMITER //
CREATE TRIGGER trg_movimiento
AFTER INSERT ON test_trigger
FOR EACH ROW
BEGIN
INSERT INTO log_trigger (mensaje)
VALUES (CONCAT('Movimiento de tipo ', NEW.tipo,
' para producto ', NEW.producto_id,
', cantidad: ', NEW.cantidad));
END//
DELIMITER ;Ahora puedes probar el trigger insertando datos que no se almacenarán pero que sí dispararán el trigger:
INSERT INTO test_trigger (producto_id, cantidad, tipo) VALUES (100, 50, 'entrada');
INSERT INTO test_trigger (producto_id, cantidad, tipo) VALUES (200, 10, 'salida');
-- Verificar que el trigger se ejecutó
SELECT * FROM log_trigger;| id | mensaje | timestamp |
|---|---|---|
| 1 | Movimiento de tipo entrada para producto 100, cantidad: 50 | 2024-09-15 10:00:00 |
| 2 | Movimiento de tipo salida para producto 200, cantidad: 10 | 2024-09-15 10:00:01 |
La tabla test_trigger está vacía (BLACKHOLE descartó los datos), pero el trigger se ejecutó correctamente y los registros de log se almacenaron en la tabla InnoDB. Esto te permite validar la lógica del trigger sin contaminar datos de producción.
Consideraciones técnicas
BLACKHOLE tiene algunas particularidades que conviene conocer. Aunque no almacena datos, sí mantiene la definición de la tabla y sus metadatos. Los contadores AUTO_INCREMENT no se incrementan de forma persistente, ya que no hay registros que los necesiten.
Las claves foráneas definidas en tablas BLACKHOLE no se validan, ya que no existen datos contra los cuales verificar las restricciones. Sin embargo, la sintaxis de creación sí se valida, por lo que puedes usar BLACKHOLE para comprobar que tu esquema es sintácticamente correcto.
-- Verificar que el esquema es válido sin consumir espacio
CREATE TABLE validar_esquema (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL,
fecha_registro DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_email (email)
) ENGINE = BLACKHOLE;
-- Si la creación es exitosa, el esquema es válido
-- Luego puedes cambiar a InnoDB para producción
ALTER TABLE validar_esquema ENGINE = InnoDB;Advertencia: Nunca uses BLACKHOLE para datos que necesitas conservar. Puede parecer obvio, pero en scripts automatizados que crean tablas dinámicamente, un error en la especificación del motor podría causar pérdida de datos si accidentalmente se asigna BLACKHOLE a una tabla de producción.
Consejo: Si usas BLACKHOLE como nodo intermedio de replicación, asegúrate de que el formato de log binario esté configurado como
ROWoMIXED. Con formatoSTATEMENT, algunas operaciones que dependen del estado del servidor podrían no replicarse correctamente a través del nodo BLACKHOLE.
En la siguiente sección veremos las herramientas de mantenimiento de tablas en MySQL.
Escrito por Eduardo Lázaro
