imu-note
いむたろ
いむたろ
@imutaroh
新卒エンジニア / データ基盤 × AI

What — タイムトラベル

BigQueryはテーブルの変更履歴を一定期間そのまま保持している。この仕組みがタイムトラベルで、クエリに FOR SYSTEM_TIME AS OF <時刻> を付けると「その時刻のテーブル」を読める。バックアップを取っていなくても、直近の事故なら自力で戻せるということ。

Warning

保持期間はデフォルトで7日間(データセット単位で2〜7日に変更可)。その範囲を過ぎた時点の状態はもう読めないので、気づいたらすぐ動く。なお、テーブルごと消してしまった場合はこの書き方では戻せず、UNDROP TABLE を使う。

戻し方の選択肢は3つ。

  • 安全に別テーブルへ退避する
  • 既存テーブルを丸ごと置き換える
  • 消えた行だけ差し戻す

How — データを復元する方法

方法1: 新しいテーブルに復元(推奨)

過去のデータを新しいテーブルにコピーします。現在のテーブルには一切触らないので、復元結果を見比べてから本番を差し替えられる。

CREATE TABLE `PROJECT_ID.DATASET.TABLE_RESTORED` AS
SELECT *
FROM `PROJECT_ID.DATASET.TABLE`
FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 HOUR);

方法2: 既存のテーブルを上書きして復元

既存のテーブルを過去のデータで置き換えます(注意: 現在のデータは失われます)。参照しているクエリやビューを直さずに済む反面、指定時刻を間違えると二次被害になる。

CREATE OR REPLACE TABLE `PROJECT_ID.DATASET.TABLE` AS
SELECT *
FROM `PROJECT_ID.DATASET.TABLE`
FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 HOUR);

方法3: 特定の行だけ復元

削除された行だけを復元する場合。事故のあとも新しい行が入り続けているテーブルは、丸ごと戻すと最新分まで巻き戻ってしまうので、この差分方式になる。

-- 削除された行を確認
SELECT *
FROM `PROJECT_ID.DATASET.TABLE`
FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 HOUR)
WHERE id NOT IN (
  SELECT id FROM `PROJECT_ID.DATASET.TABLE`
);

-- 削除された行を挿入
INSERT INTO `PROJECT_ID.DATASET.TABLE`
SELECT *
FROM `PROJECT_ID.DATASET.TABLE`
FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 HOUR)
WHERE id NOT IN (
  SELECT id FROM `PROJECT_ID.DATASET.TABLE`
);

まず SELECT で「何が戻るのか」を目視してから INSERT する順番が大事。いきなり書き込むと、重複行を作って壊し直すことになる。

関連