Поддержка транзакций (ACID)
Случай 1: INSERT в одну партицию одной таблицы семейства MergeTree*
Это транзакционно (ACID), если вставляемые строки упакованы и вставлены как один блок (см. Заметки):
- Атомарность: INSERT либо выполняется, либо отклоняется целиком: если подтверждение отправлено клиенту, значит, все строки были вставлены; если клиенту отправлена ошибка, значит, строки не были вставлены.
- Согласованность: если нет нарушений ограничений таблицы, то все строки в INSERT вставляются и INSERT выполняется; если ограничения нарушены, строки не вставляются.
- Изоляция: параллельные клиенты наблюдают согласованный снимок таблицы - состояние таблицы либо такое, как оно было до попытки INSERT, либо после успешного INSERT; частичное состояние не видно. Клиенты внутри другой транзакции имеют изоляцию снимков, в то время как клиенты вне транзакции имеют уровень изоляции чтения непроверенных данных.
- Долговечность: успешный INSERT записывается в файловую систему перед ответом клиенту, на одной реплике или нескольких репликах (контролируется настройкой
insert_quorum), и ClickHouse может попросить ОС синхронизировать данные файловой системы на носителе (контролируется настройкойfsync_after_insert). - INSERT в несколько таблиц с одним запросом возможен, если участвуют материализованные представления (INSERT от клиента идет в таблицу, у которой есть связанные материализованные представления).
Случай 2: INSERT в несколько партиций одной таблицы семейства MergeTree*
То же, что и в Случае 1 выше, с этой деталью:
- Если таблица имеет много партиций и INSERT охватывает многие партиции, то вставка в каждую партицию является транзакционной сама по себе.
Случай 3: INSERT в одну распределенную таблицу семейства MergeTree*
То же, что и в Случае 1 выше, с этой деталью:
- INSERT в распределенную таблицу не является транзакционным целиком, в то время как вставка в каждую шард является транзакционной.
Случай 4: Использование буферной таблицы
- Вставка в буферные таблицы не является ни атомарной, ни изолированной, ни согласованной, ни долговечной.
Случай 5: Использование async_insert
То же, что и в Случае 1 выше, с этой деталью:
- атомарность обеспечивается даже если
async_insertвключен иwait_for_async_insertустановлен в 1 (по умолчанию), но еслиwait_for_async_insertустановлен в 0, то атомарность не обеспечивается.
Заметки
- Строки, вставленные из клиента в каком-либо формате данных, упаковываются в один блок, когда:
- формат вставки основан на строках (например, CSV, TSV, Values, JSONEachRow и пр.) и данные содержат меньше
max_insert_block_sizeстрок (~1 000 000 по умолчанию) или меньшеmin_chunk_bytes_for_parallel_parsingбайт (10 МБ по умолчанию) в случае использования параллельного разбора (включен по умолчанию) - формат вставки основан на колонках (например, Native, Parquet, ORC и пр.) и данные содержат только один блок данных
- формат вставки основан на строках (например, CSV, TSV, Values, JSONEachRow и пр.) и данные содержат меньше
- Размер вставленного блока может зависеть от множества настроек (например:
max_block_size,max_insert_block_size,min_insert_block_size_rows,min_insert_block_size_bytes,preferred_block_size_bytesи т.д.) - Если клиент не получил ответа от сервера, клиент не знает, была ли транзакция успешной, и он может повторить транзакцию, используя свойства вставки один раз.
- ClickHouse использует MVCC с изоляцией снимков для параллельных транзакций.
- Все свойства ACID действительны даже в случае аварийного завершения сервера.
- Либо
insert_quorumв разные AZ, либоfsyncдолжны быть включены, чтобы обеспечить долговечные вставки в типичной настройке. - "Согласованность" в терминах ACID не охватывает семантику распределенных систем, см. https://jepsen.io/consistency, которая контролируется различными настройками (select_sequential_consistency).
- Это объяснение не охватывает новую функциональность транзакций, которая позволяет осуществлять полнофункциональные транзакции над несколькими таблицами, материализованными представлениями для нескольких SELECT и т.д. (см. следующий раздел о транзакциях, коммитах и откатах).
Транзакции, Коммит и Откат
В дополнение к функциональности, описанной в верхней части этого документа, ClickHouse имеет экспериментальную поддержку транзакций, коммитов и функциональности откатов.
Требования
- Разверните ClickHouse Keeper или ZooKeeper для отслеживания транзакций
- Только атомарные базы данных (по умолчанию)
- Только движок таблицы Non-Replicated MergeTree
- Включите экспериментальную поддержку транзакций, добавив эту настройку в
config.d/transactions.xml:
Заметки
- Это экспериментальная функция, и изменения следует ожидать.
- Если во время транзакции происходит исключение, вы не можете зафиксировать транзакцию. Это включает все исключения, в том числе исключения
UNKNOWN_FUNCTION, вызванные опечатками. - Вложенные транзакции не поддерживаются; завершается текущая транзакция и начинается новая.
Конфигурация
Эти примеры предназначены для одноузлового сервера ClickHouse с включенным ClickHouse Keeper.
Включение экспериментальной поддержки транзакций
Основная конфигурация для одного узла сервера ClickHouse с включенным ClickHouse Keeper
Смотрите документацию по развертыванию для получения подробной информации о развертывании сервера ClickHouse и правильном кворуме узлов ClickHouse Keeper. Конфигурация, представленная здесь, предназначена для экспериментальных целей.
Пример
Проверьте, что экспериментальные транзакции включены
Выпустите BEGIN TRANSACTION или START TRANSACTION, за которым следует ROLLBACK, чтобы проверить, что экспериментальные транзакции включены и что ClickHouse Keeper включен, поскольку он используется для отслеживания транзакций.
Если вы видите следующую ошибку, проверьте файл конфигурации, чтобы убедиться, что allow_experimental_transactions установлен в 1 (или любое значение, отличное от 0 или false).
Вы также можете проверить ClickHouse Keeper, выполнив
ClickHouse Keeper должен ответить imok.
Создайте таблицу для тестирования
Создание таблиц не является транзакционным. Выполните этот DDL-запрос вне транзакции.
Начните транзакцию и вставьте строку
Вы можете выполнять запросы к таблице из транзакции и увидеть, что строка была вставлена, даже если она ещё не была зафиксирована.
Откатить транзакцию и снова выполнить запрос к таблице
Убедитесь, что транзакция откатилась:
Завершите транзакцию и снова выполните запрос к таблице
Инспекция транзакций
Вы можете исследовать транзакции, выполняя запросы к таблице system.transactions, но имейте в виду, что вы не можете выполнять запросы к этой таблице из сеанса, который находится в транзакции. Откройте вторую сессию clickhouse client, чтобы выполнить запрос к этой таблице.
Подробнее
Смотрите этот мета-вопрос, чтобы ознакомиться с более обширными тестами и быть в курсе прогресса.