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

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

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

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