Snowflake「Stream is stale」エラーの原因とストリーム再構築の手順を解説

Snowflakeで発生する「Stream is stale」エラーの原因とストリーム再構築手順を示す解説図 Snowflake
この記事をシェアする𝕏B!FacebookLINEPocket

はじめに:「Stream is stale」って何が起きてるの?

Snowflakeで STREAM(ストリーム) を使ってデータの変更を追いかけていたら、ある日突然こんなエラーに出会ったことはありませんか?

Base table 'MY_DB.PUBLIC.MY_TABLE' dropped, cannot read from stream 'MY_STREAM'
-- もしくは
Stream 'MY_STREAM' is stale. Recreate the stream to resume tracking changes.

「stale」は英語で「古くなった・賞味期限切れ」という意味です。つまりこのエラーは、「あなたのストリームは古くなりすぎて、もう変更データを取得できませんよ」という Snowflake からのメッセージなのです。この記事では、なぜこれが起きるのか、どう直すのかを、わかりやすく解説します。

そもそもSTREAMとは?

STREAMは、テーブルに対して「いつ・どこが・どう変わったか」を記録してくれる 変更データキャプチャ(CDC) の仕組みです。テーブルにINSERT/UPDATE/DELETEが起きると、ストリームがその差分を見えるようにしてくれます。

ポイントは、ストリームは 「オフセット」 という “前回どこまで読んだか” のしおりを内部で持っていることです。このしおりから現在までの差分を返してくれるイメージです。

「Stream is stale」になる本当の原因

ストリームが差分を返すには、ベーステーブルの過去データ(Time Travel領域)が残っている必要があります。ここがポイントです!

原因①:オフセットが保持期間を超えた

ストリームは、消費(クエリ)されないままベーステーブルの DATA_RETENTION_TIME_IN_DAYS(デフォルト1日、最大Enterprise版で90日)を超えてしまうと、過去データを参照できなくなりstaleになります。

正確には、ストリームには STALE_AFTER というタイムスタンプがあり、これを過ぎると古くなります。Time Travelの仕組みと深く関係しているため、Snowflake Time TravelとFail-safe入門|誤操作からデータを守る2層バックアップも合わせて読むと理解が深まりますよ。

原因②:ベーステーブルが削除/再作成された

DROP TABLECREATE TABLE や、CREATE OR REPLACE TABLE をすると、テーブルのIDが変わるためストリームは追跡先を失います。

原因③:長期間タスクが止まっていた

ストリームをTASKで定期消費している場合、タスクが SUSPENDED 状態のまま放置されると、その間にオフセットが古くなりstaleになります。タスクが動かないトラブルはSnowflakeタスクが動かない原因と「Task is suspended」エラー解決ガイドを参考にしてみてください。

状態を確認してみよう

まずはストリームが本当にstaleかどうか、Snowsightのワークシートで以下のSQLを実行して確認します。

-- ストリームの詳細を見る
SHOW STREAMS LIKE 'MY_STREAM';

-- もしくは情報スキーマから確認
SELECT name, table_name, stale, stale_after, mode
FROM   MY_DB.INFORMATION_SCHEMA.STREAMS
WHERE  name = 'MY_STREAM';

STALE 列が TRUE になっていればアウトです。STALE_AFTER 列の時刻も合わせて確認しましょう。

SnowsightワークシートでSHOW STREAMSおよびINFORMATION_SCHEMA.STREAMSを実行し、MY_STREAMのSTALE列がTRUE、STALE_AFTER列に失効時刻が表示された画面のスクリーンショットで、ストリームが陳腐化した状態を確認する例

復旧手順:ストリームを再構築する

残念ながら、一度staleになったストリームは元には戻せません。作り直しが基本です。以下の流れで対応しましょう。

-- 1) 既存ストリームを削除
DROP STREAM IF EXISTS MY_DB.PUBLIC.MY_STREAM;

-- 2) 同じ名前で再作成(現時点を起点にする)
CREATE OR REPLACE STREAM MY_DB.PUBLIC.MY_STREAM
  ON TABLE MY_DB.PUBLIC.MY_TABLE
  APPEND_ONLY = FALSE
  SHOW_INITIAL_ROWS = FALSE;

-- 3) 動作確認
SELECT * FROM MY_DB.PUBLIC.MY_STREAM LIMIT 10;

もし 過去にさかのぼって差分を取り直したい 場合は、AT | BEFORE 句でTime Travel時点を指定して作成できます(保持期間内に限ります)。

CREATE OR REPLACE STREAM MY_STREAM
  ON TABLE MY_TABLE
  AT (OFFSET => -60*60);  -- 1時間前を起点に

再発防止のベストプラクティス

  • 定期的に消費する:TASKでストリームを毎時/毎日読み取り、オフセットを進める習慣をつけましょう。
  • 保持期間を延ばす:重要なテーブルは ALTER TABLE ... SET DATA_RETENTION_TIME_IN_DAYS = 14; のように余裕を持たせます。
  • 監視を入れるSTALE_AFTER が近づいたらSlack通知するなど、アラート運用が安心です。
  • テーブル再作成は要注意CREATE OR REPLACE TABLE はストリームを壊します。可能なら ALTER TABLEINSERT OVERWRITE を検討しましょう。

まとめ

「Stream is stale」は怖いエラーに見えますが、要は 「オフセットが古すぎて差分を取れません」 という素直なサインです。原因は保持期間切れ・テーブル再作成・タスク停止のいずれか。落ち着いて状態を確認し、ストリームを作り直してから運用ルールを見直しましょう。これで安心してCDCパイプラインを動かせるようになります!

参考リンク

関連記事

この記事をシェアする𝕏B!FacebookLINEPocket