ALTER TABLE изменяют настройки таблицы или данные:
Большинство запросов
ALTER TABLE поддерживаются только для таблиц *MergeTree, Merge и Distributed.ALTER изменяют представления:
Эти операторы
ALTER изменяют сущности, связанные с ролевым управлением доступом:
Объединение нескольких действий в одном ALTER
Один оператор ALTER TABLE может содержать несколько действий через запятую, поэтому изменения, которые иначе пришлось бы выполнять последовательностью отдельных команд, можно объединить в одном операторе:
ALTER, то, какая настройка управляет этим ожиданием, определяется действием, а не оператором: действие, выполняемое через механизм мутаций, например MATERIALIZE INDEX, регулируется настройкой mutations_sync, а действия с метаданными — настройкой alter_sync. Поэтому объединение таких действий в одном операторе не переводит их под одну настройку. Какие действия охватывает каждая настройка, см. в разделе Синхронность запросов ALTER, а об ограничении, которое действует для такого смешанного оператора в базе данных Replicated, — в разделе Объединение секций MATERIALIZE INDEX.
Мутации
ЗапросыALTER, предназначенные для изменения данных в таблице, реализованы с помощью механизма под названием «мутации», в частности ALTER TABLE … DELETE и ALTER TABLE … UPDATE. Это асинхронные фоновые процессы, похожие на слияния в таблицах MergeTree, которые создают новые «мутированные» версии частей.
Для таблиц *MergeTree мутации выполняются путем перезаписи частей данных целиком.
Атомарности здесь нет — части заменяются мутированными, как только они готовы, и запрос SELECT, который начал выполняться во время мутации, увидит данные из уже измененных частей вместе с данными из частей, которые еще не были изменены.
Мутации полностью упорядочены по порядку создания и применяются к каждой части именно в этом порядке. Кроме того, мутации частично упорядочены относительно запросов INSERT INTO: данные, вставленные в таблицу до отправки мутации, будут изменены, а данные, вставленные после этого, — нет. Обратите внимание, что мутации никак не блокируют вставки.
Запрос мутации возвращает результат сразу после добавления записи о мутации (в случае реплицируемых таблиц — в ZooKeeper, для нереплицируемых таблиц — в файловую систему). Сама мутация выполняется асинхронно с использованием настроек системного профиля. Для отслеживания прогресса мутаций можно использовать таблицу system.mutations. Успешно отправленная мутация продолжит выполняться, даже если серверы ClickHouse будут перезапущены. После отправки мутацию нельзя откатить, но, если она по какой-либо причине зависла, ее можно отменить запросом KILL MUTATION.
Записи о завершенных мутациях удаляются не сразу (количество сохраняемых записей определяется параметром движка хранения finished_mutations_to_keep). Более старые записи о мутациях удаляются.
Стоимость выполнения и завершение
При планированииALTER TABLE отличайте изменение метаданных от работы, которую требуется выполнить над существующими частями данных. Будет ли клиент ожидать завершения, зависит от операции: alter_sync управляет операциями над метаданными и MODIFY COLUMN, включая преобразования типов с перезаписью данных; mutations_sync управляет фоновыми мутациями, такими как UPDATE, DELETE и MATERIALIZE .... Не ориентируйтесь на фиксированную длительность при эксплуатации: стоимость зависит от объёма метаданных, количества затрагиваемых частей и байтов, стоимости преобразования и текущей фоновой нагрузки.
Синхронность запросов ALTER
По умолчанию запросы ALTER для нереплицируемых таблиц ожидают завершения своей работы. При alter_sync = 0 запрос ALTER, выполняющий фоновую работу, может вернуть управление до её завершения. Для реплицируемых таблиц запрос добавляет в ZooKeeper инструкции для соответствующих действий, а сами действия выполняются как можно скорее. Запрос может ждать завершения этих действий на всех репликах.
Для запросов ALTER, создающих мутации через механизм выполнения мутаций (например, UPDATE, DELETE, MATERIALIZE INDEX, MATERIALIZE PROJECTION, MATERIALIZE COLUMN, APPLY DELETED MASK, APPLY PATCHES, CLEAR STATISTIC, MATERIALIZE STATISTIC и другие), синхронность определяется настройкой mutations_sync.
Для других запросов ALTER, включая перезапись данных при MODIFY COLUMN, ожиданием управляет настройка alter_sync.
С помощью настройки replication_wait_for_inactive_replica_timeout можно указать, как долго (в секундах) ждать, пока неактивные реплики выполнят все запросы ALTER.
Для всех запросов
ALTER: если alter_sync = 2 и некоторые реплики остаются неактивными дольше времени, указанного в настройке replication_wait_for_inactive_replica_timeout, генерируется исключение UNFINISHED. При alter_sync = 3 ожидание неактивных реплик не выполняется, поэтому исключение не генерируется.Одновременное назначение ALTER для одной таблицы
В реплицируемых таблицах быстрая последовательная отправка нескольких отдельных операторов ALTER для одной и той же таблицы может завершиться ошибкой CANNOT_ASSIGN_ALTER (код 517). В реплицируемом пути эта ошибка возникает, если реплика ещё не применила некоторые предыдущие ALTER (версия метаданных всё ещё отстаёт от общей версии метаданных — сервер может сообщить, что реплика «still not applied some of previous alters» или «Probably too many alters executing concurrently»). Это условие может сохраняться даже после того, как предыдущий ALTER уже был назначен. Это общее условие одновременного выполнения ALTER метаданных / мутаций — оно не ограничивается операторами, относящимися только к мутациям. Обычные одновременные изменения метаданных (ADD / DROP / MODIFY и аналогичные) могут вызывать тот же код, допускающий повторную попытку (см., например, путь повторной попытки в tests/queries/0_stateless/03518_alter_logical_race.sh).
Подходы, позволяющие избежать состояния гонки:
- Объединяйте независимые операции с метаданными в один
ALTERс несколькими секциями, если это допускается грамматикой (например, несколько секцийADD INDEX), как описано в разделе Объединение нескольких действий в одномALTER. - Выполняйте операторы
ALTERпоследовательно и повторяйте попытку при коде 517, пока предыдущиеALTERне будут применены на реплике. - Для
ALTER, создающих мутации, дождитесь завершения предыдущей мутации, используя документированный наблюдаемый признак, напримерmutations_syncилиis_doneвsystem.mutations, прежде чем отправлять следующий.
Объединение секций MATERIALIZE INDEX
В одном операторе ALTER может содержаться несколько секций MATERIALIZE INDEX. Рассматриваемый в исходном коде случай — объединение нескольких секций ADD INDEX с MATERIALIZE INDEX для тех же новых индексов в одном операторе (см. tests/queries/0_stateless/02911_add_index_and_materialize_index.sql). Такая объединённая форма ADD INDEX + MATERIALIZE INDEX сочетает сегмент AlterCommand с сегментом MutationCommand, поэтому DatabaseReplicated отклоняет её с ошибкой QUERY_IS_PROHIBITED (InterpreterAlterQuery::validateReplicatedDatabaseSegments). Пример 02911 допустим для обычных баз данных (не DatabaseReplicated); в DatabaseReplicated выполняйте изменения метаданных и мутации материализации отдельными операторами.
В текущей реализации каждая секция MATERIALIZE INDEX разрешается относительно снимка метаданных таблицы при подготовке мутации, поэтому формы с несколькими секциями только MATERIALIZE INDEX для уже существующих индексов проходят тот же путь подготовки (только мутация, поэтому они остаются в пределах одного сегмента). Эта конкретная форма пока не покрыта отдельным stateless-тестом; до появления такого покрытия считайте её текущим поведением реализации, а не отдельно гарантированным контрактом.
Если требуется упорядоченное применение мутаций, можно по-прежнему выполнять по одному MATERIALIZE INDEX в каждом операторе и ждать завершения с помощью mutations_sync.