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