APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

データレイクハウスにおけるトランザクション競合とその解決策

※本記事は、Data + AI Summit のセッションを現地で視聴したエンジニアが、内容をできる限り客観的に共有することを目的に、生成AIを活用して作成したものです。 ― エーピーコミュニケーションズ Lakehouse部

データレイクハウスの運用が広がる中で、多くのデータエンジニアが直面する課題の一つが「トランザクションの競合」です。特に、複数のデータソースから同時に書き込みや更新が行われる環境では、データの一貫性を保ちながら高いスループットを維持することは簡単ではありません。

本記事では、Data + AI Summitで発表されたAsanaのソフトウェアエンジニア、Dima Kamalov氏による講演「Reducing Transaction Conflicts in Databricks—Fundamentals and Applications at Asana」をもとに、DatabricksとDelta Lakeにおけるトランザクション競合の基本から、それを解決するための具体的な手法、そしてAsana社における実用例までを深く掘り下げます。データレイクの同時実行性に課題を感じている方にとって、実践的なヒントが得られる内容です。

Delta LakeにおけるACIDトランザクションの基礎

Delta Lakeはデータレイク上でACIDトランザクションを実現し、複数の処理が同時に実行されてもデータの整合性を保ちます。中でも同時実行性に関わる「Isolation(分離性)」には、主に以下の2つのレベルが用意されています。

  • Write Serializable(デフォルト) オプティミスティックコンカレンシー制御を用い、書き込みトランザクションを順序付けてコミットします。高いスループットを維持しつつ、一貫したデータ状態を提供します。

  • Serializable 読み取りと書き込みを含む全トランザクションを完全に直列化されたかのように扱います。一貫性は最も厳格ですが、衝突が検出された場合はトランザクションが失敗し、リトライの必要が生じます。

同時実行時に発生する具体的な競合パターン

  1. Append系処理(INSERT): 新規ファイルへの追記が行われるため、通常はファイル単位でのロック競合が起こりにくく、衝突率は低めです。

  2. 更新・削除・MERGE:

    • セマンティックな競合: 同一レコードへの同時更新など、論理的に食い違いが起こるとトランザクションは失敗します。
  3. 実装上の競合: 異なる行を更新していても、物理的に同じデータファイルを読み書きする場合は競合と見なされ、ConcurrentModificationExceptionが発生することがあります。

競合を削減するための実践的アプローチ

  1. パーティショニングの活用 特定の列(例: 日付や地域)でテーブルをパーティション分割すると、異なるパーティションへの書き込みは別ファイル群を対象とするため、競合を減らせます。

ポイント: クエリ実行時にパーティションキーをフィルタ条件(WHERE句)として指定し、不要なパーティションへのスキャンやロックを避けるようにしましょう。

2. 削除ベクトル(Deletion Vectors)の活用 ファイル全体を再書き込みせずに、無効化する行番号だけをメタデータに記録します。これにより細かな行レベル更新でも競合範囲を限定でき、パーティショニングと組み合わせずに同時実行性を高められます。

Asanaにおける大規模同時更新への挑戦:Blind Append & Batch MERGE

Asanaでは数百もの上流テーブルから同時に下流テーブルへのMERGE INTOを行う必要があり、従来の並列MERGEでは衝突が頻発しました。そこで採用されたのが、2ステージ構成のパターンです。

  1. Blind Appendステージ 各上流変更をすべて中間テーブルへINSERTで書き込み。単純な追記のみなので衝突が起きにくい。

  2. Batch MERGEステージ 中間テーブルに溜まった変更を束ね、一度だけMERGE INTOで下流テーブルに適用。並列のMERGEがなくなるため、競合は大幅に減少します。

この手法により、Asanaは数百規模の同時更新を安定して処理できるようになりました。

各手法の比較と選択のポイント

まとめ

Delta Lakeでは、セマンティックな競合と実装上の競合に対し、それぞれ適切な手法を選ぶことで同時実行性と信頼性を両立できます。基本的なパーティショニングや削除ベクトルの適用から始め、要件に応じてアーキテクチャレベルの工夫(Blind Append & Batch MERGEなど)を導入すると、運用の安定性が大きく向上します。ご自身の環境で発生しているトランザクションエラーの背景を理解し、最適なアプローチを選ぶ参考になれば幸いです。