Перейти к основному содержимому
Перейти к основному содержимому

Поддержка транзакций (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 и т.д.) и данные содержат только один блок данных.
  • Размер вставленного блока в общем может зависеть от многих настроек (например: 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 и т.д. (см. следующий раздел о Транзакциях, Коммитах и Откатах).

Транзакции, Коммиты и Откаты

Experimental feature. Learn more.
Not supported in ClickHouse Cloud

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

Дополнительные детали

Смотрите этот мета-вопрос, чтобы увидеть гораздо более обширные тесты и быть в курсе прогресса.