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