「本番テーブルをうっかりDROPしてしまった」——データ基盤を運用していれば、誰もが一度は肝を冷やす場面です。Snowflakeには、こうした誤削除・誤更新に備える二段構えの仕組みとして、Time TravelとFail-safeが標準で備わっています。ただし両者は役割も復旧手段もまったく異なり、しかも設定を誤ると静かにストレージ課金を押し上げます。本記事では、保持期間の考え方、UNDROPやAT/BEFOREによる具体的な復旧手順、7日間のFail-safeの位置づけ、そしてコストを膨らませないための設計を、AWS上での運用を前提に整理します。

01CDPという考え方:Active → Time Travel → Fail-safe

Snowflakeの誤削除・誤更新対策は、単発の「バックアップ機能」ではなく、Continuous Data Protection(CDP)という一連のライフサイクルとして設計されています。テーブルのデータは、現役の最新状態である「Active」から始まり、更新・削除・DROPが発生すると古い版が「Time Travel」の対象として一定期間保持され、さらにその後ろに「Fail-safe」が7日間続きます。この3つの状態が時間軸上で連続している、というモデルを最初に押さえておくと、以降の設計判断がぶれません。

重要なのは、この3段階が「誰が触れるか」で明確に分かれている点です。Active と Time Travel は利用者自身がSQLで参照・復旧できますが、Fail-safe はSnowflakeが内部的に保持する領域で、利用者からはクエリも復旧もできません。CDP自体はすべてのアカウントで追加料金なく使える標準機能ですが、後述するとおり保持している間はストレージ課金の対象になり続けます。

現場のコツ:Time TravelとFail-safeは「論理障害(誤操作)」への保険であって、リージョン障害やアカウント消失に効くDR機能ではありません。事業継続の観点では、データベースのレプリケーション(クロスリージョン/クロスクラウド)を別レイヤーとして必ず切り分けて設計してください。

02Time Travel:保持期間とエディションの違い

Time Travelの挙動を決めるのが DATA_RETENTION_TIME_IN_DAYS パラメータです。既定値は1日(24時間)で、すべてのアカウントで自動的に有効になっています。この保持期間の上限は、実はエディションによって大きく異なります。Standard Edition では永続テーブルでも 0 または 1 日までしか設定できません。一方、Enterprise Edition 以上であれば、永続オブジェクトに対して 0〜90 日の範囲で保持期間を指定できます。「90日戻せる」はEnterprise前提の話だ、という点は要注意です。

保持期間はアカウント・データベース・スキーマ・テーブルの各レベルで設定でき、上位で設定した値は下位に継承されます。したがって、アカウント既定を長めにすると、意図しないテーブルまで一律に長い履歴を抱えることになります。加えて、一時的な作業用の Transient テーブルや Temporary テーブルは、エディションを問わず Time Travel が最大1日までに制限され、後述する Fail-safe も持ちません。ステージングや中間テーブルをどの種別で作るかは、そのまま保護レベルとコストの設計になります。

現場のコツ:アカウントに MIN_DATA_RETENTION_TIME_IN_DAYS が設定されていると、テーブル側で保持期間を短くしても実効値は「MAX(テーブル値, MIN値)」で決まります。「テーブルで0日にしたのに履歴が減らない」という相談の多くは、この最小値の存在が原因です。

03復旧の実務:UNDROP と AT / BEFORE

誤ってテーブルを消した場合、保持期間内であれば UNDROP TABLE sales; の一文で直前の状態に戻せます。UNDROP はテーブルだけでなく、スキーマ(UNDROP SCHEMA)やデータベース(UNDROP DATABASE)にも使えます。データの中身を過去の時点で参照したいときは、SELECT や CREATE ... CLONE に AT / BEFORE 句を付けます。指定方法は3種類あり、時刻を直接指す TIMESTAMP、現在から何秒前かを指す OFFSET、特定のクエリ実行「直前」を指す STATEMENT(クエリID)です。

たとえば「5分前の状態を見たい」なら SELECT * FROM orders AT(OFFSET => -300);、「あの一括更新を流す直前に戻したい」なら CREATE TABLE orders_restored CLONE orders BEFORE(STATEMENT => '<query_id>'); のように、過去状態をそのまま新しいテーブルとして切り出せます。復旧作業では、まず CLONE で別テーブルに復元して内容を検証し、確認できてから本番へ差し替える、という段取りが安全です。

現場のコツ:UNDROPが失敗する典型は「同名オブジェクトを作り直してしまった」ケースです。UNDROPは“直近でDROPされた同名オブジェクト”を戻す仕様なので、先に既存を退避リネームしてからUNDROPする、という順序を徹底してください。焦って作り直すと、戻せるはずのものが戻せなくなります。

04Fail-safe:7日間の最後の砦

Time Travelの保持期間が切れると、データはすぐ消えるわけではなく、Fail-safeへ移ります。Fail-safeは永続テーブルに対してのみ提供される、固定7日間・変更不可の保護期間です。ここは利用者が設定を変えることも、クエリで参照することもできません。復旧が必要な場合はSnowflakeのサポートに依頼する形になり、しかもベストエフォート(数時間〜数日を要することがある内部復旧)であって、セルフサービスの即時復旧とは性格が異なります。

言い換えれば、Fail-safeは「Time Travelでも救えなかった致命的な事態に対する、Snowflake管理下の最終手段」です。日常の誤操作はTime Travelの範囲内で自力復旧できるよう保持期間を設計し、Fail-safeはあくまで最後の砦として捉えるのが正しい距離感です。下図に、Active・Time Travel・Fail-safeの3状態と、それぞれ誰が復旧できるかを時間軸で示します。

データ保護のライフサイクル(CDP) UPDATE / DELETE / DROP Active 最新データ Time Travel 0〜90日(エディション依存) 自分で復旧できる Fail-safe 7日・固定 消去 利用者がSQLで復旧 Snowflakeサポートのみ この期間はストレージ課金が継続する
図1:更新・削除されたデータはTime Travel → Fail-safeの順に保持され、その間ずっとストレージ課金の対象になる。Fail-safeは利用者からは触れず、復旧はSnowflakeサポート経由に限られる。

05ストレージ課金の実像とテーブル種別の設計

CDPの落とし穴は、ここに集約されます。ストレージ課金は Active/Time Travel/Fail-safe のどの状態でも発生し、しかもこの3状態は連続しているため、更新・削除された古いデータは「Time Travelの保持期間 + Fail-safeの7日」ぶん、消えずに課金され続けます。Enterprise Edition で永続テーブルに90日のTime Travelを設定すると、履歴は最長で 90 + 7 = 97 日ぶん保持され得る、という計算です(Standard なら 1 + 7 = 最長8日)。

救いは、Snowflakeが保持するのは「変更された行を復元するのに必要な差分情報」だけで、テーブル全体のコピーを毎日取るわけではない点です。ただし例外があり、TRUNCATE や DROP を実行すると、その時点の全量が履歴として残ります。したがって、更新頻度が高いテーブルや、洗い替え(全件洗い替え)運用のテーブルほど、履歴の実体が積み上がりやすい、という傾向を押さえておく必要があります。下図のとおり、テーブル種別の選択がそのまま保護レベルとコストのトレードオフになります。

テーブル種別で「守り」と「コスト」を設計する Permanent 本番マスタ・監査対象 Time Travel:0〜90日 Fail-safe:7日あり 最長97日ぶん課金 最も手厚いが最も高い Transient 中間・ステージング Time Travel:最大1日 Fail-safe:なし 最大1日ぶん課金 低コスト・再生成前提 Temporary セッション内の一時作業 Time Travel:最大1日 Fail-safe:なし セッション終了で消滅 永続化しない前提
図2:永続テーブルは手厚い一方でFail-safe込みで最長97日ぶん課金される。中間・一時データはTransient/TemporaryにすることでFail-safeを外し、履歴コストを抑えられる(ただしTime Travel満了後はSnowflakeでも復旧不可)。
現場のコツ:Time Travelの課金は“差分”が基本ですが、TRUNCATE/DROPは全量コピーが履歴に残ります。日次で全件洗い替えするテーブルを長い保持期間の永続テーブルにしていると、履歴が雪だるま式に膨らみます。洗い替え系はTransient化を第一候補に検討してください。

06検証で先に踏み抜いた「保持期間の課金増」

私たちが複数業種でSnowflakeを設計・運用してきた中で、この保持期間の設計は必ず検証(PoC)段階で作り込むテーマにしています。あるプロジェクトの検証環境では、「戻せる日数は長いほど安心」という発想で、アカウント既定の DATA_RETENTION_TIME_IN_DAYS を一律で長めに設定し、その配下に高頻度更新テーブルや日次洗い替えテーブルをそのまま置いてみました。結果、Fail-safeの7日と合わせて履歴の実体が想定以上に積み上がり、ストレージ課金が読みより明確に増える挙動を、本番投入の前に把握できました。

この学びを踏まえ、本番では「テーブルの重要度で保持期間を階層化する」方針に切り替えました。監査・復旧要件のある本番マスタは永続テーブルで必要日数だけ保持し、中間・ステージングはTransientにしてFail-safeを外し、セッション限りの作業はTemporaryにする、という具合です。あわせて、ORGANIZATION/ACCOUNT_USAGE 系のストレージメトリクスを監視し、履歴容量が跳ねたテーブルを早期に検知できるようにしています。「先に検証で踏み抜き、本番では未然に防ぐ」——この順序を守ることで、コスト事故を運用に持ち込まずに済みました。

現場のコツ:保持期間は「全社一律の長め設定」ではなく「テーブル階層ごとの最小十分」で設計するのが鉄則です。90日が本当に必要なのは一部の本番マスタだけ、というケースがほとんどです。まずは既定を短めに置き、必要なテーブルだけ明示的に延ばす、という引き算の設計に倒してください。

07AWS上での復旧設計に落とし込む

SnowflakeはAWS上で動く前提を活かすと、Time Travel/Fail-safeの位置づけがよりクリアになります。標準テーブルの実体は、Snowflakeが管理するS3上に暗号化されたマイクロパーティションとして格納され、鍵は階層型の鍵管理で保護されます。Business Critical Edition 以上で使える Tri-Secret Secure を用いれば、AWS KMS の顧客管理キーをこの鍵階層に組み込み、キーの無効化によるアクセス遮断まで含めた統制が可能になります。つまりデータ保護は「Time Travel/Fail-safe(論理復旧)」と「KMS(暗号統制)」の二軸で考えるとよく整理できます。

一方で、AWSの運用経験者ほど陥りやすいのが、Time Travel/Fail-safeをRDSスナップショットやS3バージョニング、AWS Backupと同じ「バックアップ」として扱ってしまう発想です。CDPはあくまでSnowflake内部の論理復旧の仕組みで、リージョン障害やアカウント消失には効きません。事業継続の観点では、データベースのレプリケーションによるクロスリージョン/クロスクラウドの冗長化、そして重要データのS3等への外部エクスポートを、別レイヤーとして明示的に設計する必要があります。EMWでは、AWS側のバックアップ・DR設計とSnowflakeのCDP設計を地続きで捉え、「日常の誤操作はTime Travelで自力復旧、致命的事象はレプリケーションとFail-safeで多層防御」という現実的な復旧体制に落とし込んでいます。

現場のコツ:Fail-safeからの復旧はSnowflakeサポートへの依頼が前提で、AWS Supportのケース起票と同じくベストエフォートです。「7日あるから大丈夫」と即時復旧を期待せず、自力で戻せるTime Travelの範囲を、業務が許容できる復旧目標(RPO)に合わせて設計しておくことが、いざというときの明暗を分けます。

参考情報(一次情報)

EMWは、AWS上でのSnowflake設計から保持期間の最適化・復旧体制の整備までを一気通貫でご支援しますので、コストと安全性の両立にお悩みならお気軽にご相談ください。

相談する
← ブログ一覧へ戻る