Поддержка транзакций (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
, чтобы выполнить запрос к этой таблице.
Подробнее
Смотрите этот мета-вопрос, чтобы ознакомиться с более обширными тестами и быть в курсе прогресса.