ALTER TABLE modifican la configuración de la tabla o sus datos:
La mayoría de las consultas
ALTER TABLE solo son compatibles con tablas *MergeTree, Merge y Distributed.ALTER manipulan vistas:
Estas sentencias
ALTER modifican entidades relacionadas con el control de acceso basado en roles:
Mutaciones
ALTER destinadas a modificar datos de tablas se implementan mediante un mecanismo llamado “mutaciones”, en particular ALTER TABLE … DELETE y ALTER TABLE … UPDATE. Son procesos asíncronos en segundo plano, similares a las fusiones en tablas MergeTree, que producen nuevas versiones “mutadas” de las partes.
En las tablas *MergeTree, las mutaciones se ejecutan reescribiendo partes de datos completas.
No hay atomicidad: las partes se sustituyen por sus versiones mutadas en cuanto están listas, y una consulta SELECT que haya comenzado a ejecutarse durante una mutación verá datos de partes que ya han sido mutadas junto con datos de partes que aún no han sido mutadas.
Las mutaciones están totalmente ordenadas según su orden de creación y se aplican a cada parte en ese orden. Las mutaciones también están parcialmente ordenadas con las consultas INSERT INTO: los datos que se insertaron en la tabla antes de que se enviara la mutación serán mutados, y los datos que se insertaron después no serán mutados. Tenga en cuenta que las mutaciones no bloquean las inserciones de ninguna manera.
Una consulta de mutación devuelve el resultado inmediatamente después de que se añade la entrada de mutación (en el caso de las tablas replicadas, en ZooKeeper; en las tablas no replicadas, en el sistema de archivos). La mutación en sí se ejecuta de forma asíncrona usando la configuración del perfil del sistema. Para seguir el progreso de las mutaciones, puede usar la tabla system.mutations. Una mutación enviada correctamente seguirá ejecutándose incluso si se reinician los servidores de ClickHouse. No hay forma de revertir la mutación una vez enviada, pero si la mutación se queda atascada por algún motivo, puede cancelarse con la consulta KILL MUTATION.
Las entradas de las mutaciones finalizadas no se eliminan de inmediato (el número de entradas conservadas lo determina el parámetro del motor de almacenamiento finished_mutations_to_keep). Las entradas de mutación más antiguas se eliminan.
Sincronía de las consultas ALTER
ALTER se realizan de forma síncrona. Para las tablas replicadas, la consulta solo agrega en ZooKeeper instrucciones para las acciones correspondientes, y dichas acciones se realizan lo antes posible. Sin embargo, la consulta puede esperar a que estas acciones se completen en todas las réplicas.
Para las consultas ALTER que crean mutaciones (p. ej., entre otras, UPDATE, DELETE, MATERIALIZE INDEX, MATERIALIZE PROJECTION, MATERIALIZE COLUMN, APPLY DELETED MASK, APPLY PATCHES, CLEAR STATISTIC, MATERIALIZE STATISTIC), la sincronía se define mediante la configuración mutations_sync.
Para otras consultas ALTER que solo modifican los metadatos, puede usar la configuración alter_sync para definir la espera.
Puede especificar cuánto tiempo (en segundos) esperar a que las réplicas inactivas ejecuten todas las consultas ALTER con la configuración replication_wait_for_inactive_replica_timeout.
Para todas las consultas
ALTER, si alter_sync = 2 y algunas réplicas permanecen inactivas durante más tiempo del especificado en la configuración replication_wait_for_inactive_replica_timeout, se lanza una excepción UNFINISHED.Asignación concurrente de ALTER en una misma tabla
ALTER independientes contra la misma tabla en rápida sucesión puede generar el error CANNOT_ASSIGN_ALTER (código 517). La ruta replicada genera este error cuando la réplica aún no ha aplicado algunos ALTER anteriores (la versión de los metadatos sigue por detrás de los metadatos comunes; el servidor puede indicar que la réplica “still not applied some of previous alters” o “Probably too many alters executing concurrently”). Esta condición puede persistir incluso después de que se haya asignado un ALTER anterior. Se trata de una condición general de ALTER de metadatos o mutaciones concurrentes; no se limita a sentencias que solo producen mutaciones. Las operaciones concurrentes habituales de modificación de metadatos (ADD / DROP / MODIFY y similares) pueden generar el mismo código reintentable (consulte, por ejemplo, la ruta de reintento cubierta por tests/queries/0_stateless/03518_alter_logical_race.sh).
Enfoques para evitar la condición de carrera:
- Combine operaciones de metadatos independientes en un único
ALTERcon varias cláusulas cuando la gramática lo permita (por ejemplo, varias cláusulasADD INDEX). - Serialice las sentencias
ALTERy vuelva a intentarlo ante el código 517 hasta que losALTERanteriores se hayan aplicado en la réplica. - Para los
ALTERque generan mutaciones, espere a que finalice la mutación anterior mediante un indicador observable documentado, comomutations_syncois_doneensystem.mutations, antes de enviar el siguiente.
Combinación de cláusulas MATERIALIZE INDEX
MATERIALIZE INDEX en un mismo ALTER. El caso cubierto en el código fuente consiste en agrupar varias cláusulas ADD INDEX junto con MATERIALIZE INDEX para esos mismos índices nuevos en una sola sentencia (consulte tests/queries/0_stateless/02911_add_index_and_materialize_index.sql). Esta forma agrupada de ADD INDEX + MATERIALIZE INDEX combina un segmento AlterCommand con un segmento MutationCommand, por lo que DatabaseReplicated la rechaza con QUERY_IS_PROHIBITED (InterpreterAlterQuery::validateReplicatedDatabaseSegments). Considere válido el ejemplo 02911 para bases de datos ordinarias (distintas de DatabaseReplicated); en DatabaseReplicated, mantenga los cambios de metadatos y las mutaciones de materialización en sentencias separadas.
En la implementación actual, cada cláusula MATERIALIZE INDEX se resuelve respecto a la instantánea de metadatos de la tabla cuando se prepara la mutación, por lo que las formas con varias cláusulas que solo materializan índices ya existentes siguen la misma ruta de preparación (solo mutación, por lo que permanecen dentro de un único segmento). Esta forma exacta aún no está cubierta por una prueba stateless específica; trátela como comportamiento de la implementación actual, no como un contrato garantizado de forma independiente, hasta que exista dicha cobertura.
Si necesita aplicar las mutaciones en orden, puede seguir emitiendo un MATERIALIZE INDEX por sentencia y esperar con mutations_sync.