В Apache Iceberg транзакции обеспечивают ACID-свойства на уровне одной таблицы. Это значит, что нативно Iceberg поддерживает атомарные операции (транзакции) только в пределах одной таблицы.

Однако в реальных сценариях иногда возникает необходимость выполнить транзакцию, затрагивающую несколько таблиц (multi-table transactions). Давайте рассмотрим, как это можно реализовать в Iceberg:


📌 Что предлагает Iceberg для транзакций на нескольких таблицах?

На данный момент Apache Iceberg не поддерживает мульти-табличные транзакции на уровне движка напрямую.

Но есть несколько подходов, как можно достичь подобного поведения:


🚩 Подходы для реализации транзакций с несколькими таблицами в Iceberg:

🟢 1. Использование внешней системы управления транзакциями (External Transaction Manager)

Это наиболее распространенный подход:

  • Используется внешняя система, такая как Apache Hive Metastore, AWS Glue, или собственная реализация.
  • Транзакция реализуется на уровне внешней системы.
  • В случае ошибки все изменения на уровне Iceberg откатываются вручную, либо перезапускаются.

Пример:

BEGIN TRANSACTION (external system)
  - Insert into Iceberg_table_1
  - Update Iceberg_table_2
  - Delete from Iceberg_table_3
COMMIT TRANSACTION (external system)

IF transaction failed:
  ROLLBACK (manually delete uncommitted snapshots)

Плюсы:

  • Работает практически с любыми движками и не зависит от встроенной поддержки транзакций.

⚠️ Минусы:

  • Необходимо явно управлять откатами изменений вручную.

  • Используя Spark или Flink, вы можете контролировать запись в несколько таблиц с помощью логики приложения.
  • Если какой-либо этап транзакции не завершился, приложение может удалить созданные snapshot’ы и восстановить состояние таблиц вручную.

Пример на Spark (упрощенно):

spark.sparkContext.setJobGroup("multi-table-transaction")
 
try {
  icebergTable1.newAppend().appendFile(file1).commit()
  icebergTable2.newAppend().appendFile(file2).commit()
} catch {
  case e: Exception => 
    // Откатываем вручную, удаляем snapshot'ы
    icebergTable1.expireSnapshots().expireOlderThan(timestampBeforeTransaction).commit()
    icebergTable2.expireSnapshots().expireOlderThan(timestampBeforeTransaction).commit()
}
 

Плюсы:

  • Простая интеграция, если приложение уже использует Spark или Flink.

⚠️ Минусы:

  • Ручное управление состоянием транзакций.

🟢 3. Использование Data Lakehouse-фреймворков (Delta Lake, Hudi поверх Iceberg)

Delta Lake и Hudi предлагают встроенную поддержку мульти-табличных транзакций.
Но на данный момент это отдельные фреймворки, а не расширения Iceberg.

⚠️ Важно:
Сейчас Iceberg не интегрируется напрямую с этими фреймворками для мульти-табличных транзакций, но архитектурно Iceberg развивается в этом направлении, и такая интеграция может появиться в будущем.


📌 Best Practice (рекомендуемый подход):

На практике чаще всего реализуется подход №1 или №2 — управление транзакциями на уровне приложения или внешней системы:

  • Используйте чёткое управление транзакциями на уровне приложения.
  • Делайте транзакции idempotent (повторно выполнимыми) и устойчивыми к сбоям.
  • Используйте time-travel возможности Iceberg для отката состояния вручную в случае ошибки.

📌 Текущие ограничения Iceberg для multi-table транзакций:


📊 Краткий итог подходов для Multi-table транзакций:

ПодходРеализацияСложностьНадежность
Внешний Transaction Manager✅ Часто используетсяСредняяСредняя-высокая
Apache Spark/Flink + manual rollback✅ Часто используетсяСредняяСредняя-высокая
Delta Lake/Hudi ( отдельные решения)ВысокаяВысокая

🚀 Заключение:

  • Iceberg обеспечивает ACID на уровне одной таблицы (single-table ACID).
  • Встроенной поддержки multi-table транзакций нет, но вы можете реализовать это внешними инструментами или логикой приложения.
  • Транзакции между несколькими таблицами реализуются вручную или с использованием внешних Transaction Managers.