Appearance
變更回滾與資料復原
核心原則:Argus 不提供「按一個按鈕就把 prod DB 倒帶」功能。
所有「回滾」都走新開一份 Plan:原始變更通過審批,回滾也必須通過審批。這條設計守住「所有變更走 Plan」核心承諾,避免 audit 軌跡被繞道。
但 Argus 提供兩個機制讓你寫倒帶 Plan 時不用憑記憶猜:DML 變更前自動備份影響的 row(PriorBackup)、DDL 變更前後自動拍 schema snapshot(sync_history)。
DML 變更:PriorBackup(執行前抓 row)
怎麼啟用
Plan 設定時開 enablePriorBackup(Plan 詳細頁右側設定 → Prior backup)。
預設 關閉 — 你必須主動勾選才會備份。
怎麼運作
備份去哪了
Argus 在你的 instance 內自動建立一個 sidecar database 叫 bbdataarchive(Oracle 是大寫 BBDATAARCHIVE),所有 PriorBackup 都寫在這。
每張被影響的原表,會在 backup DB 內生成一張 _<random>_<source_table>_<timestamp> 對應表,只放這次 UPDATE/DELETE 影響的 row(不是整表複製)。
怎麼知道備份了什麼
進 issue 詳細頁 → Task Run → 看 TaskRunLog,有兩條:
PRIOR_BACKUP_START— 備份開始時間PRIOR_BACKUP_END— 備份結束時間 +PriorBackupDetail,列出每張 source table 對應的 target table 名稱
也可以直接 SQL Editor 連 bbdataarchive database,看裡面的表清單。
支援的 engine
| Engine | PriorBackup |
|---|---|
| MySQL | ✅ |
| TiDB | ✅ |
| MSSQL | ✅ |
| PostgreSQL | ✅ |
| Oracle | ✅(backup DB 命名為 BBDATAARCHIVE) |
| Snowflake | ❌ |
| Cassandra | ❌ |
| SQLite | ❌ |
| MongoDB | ❌ |
| Spanner | ❌ |
不支援的 engine 上勾 enablePriorBackup 會被略過(看 TaskRunLog 不會有 PRIOR_BACKUP_END)。
怎麼用備份倒帶
不是按一個按鈕。你開一份新 Plan,SQL 內容是「從 bbdataarchive 把 row 倒回 source」:
sql
-- 倒帶範本(PostgreSQL):
-- 假設 PriorBackupDetail 顯示 source=public.users / target=_a1b2c3_users_20260615
INSERT INTO public.users (id, email, ...)
SELECT id, email, ... FROM bbdataarchive._a1b2c3_users_20260615
ON CONFLICT (id) DO UPDATE SET
email = EXCLUDED.email;這份 Plan:
- 走 advisor + 審批,跟原始 Plan 同等待遇
- 自動再做一次 PriorBackup(如果你想要的話)
- 進 Revision 帳本,跟原 Plan 串成完整時序
為什麼不一鍵倒帶? 一鍵 = 沒審批 = 任何能跑 rollback 的人都能改 prod 資料 = 違反「所有變更走 Plan」核心承諾。Argus 的設計是 rollback 也是變更,rollback 也要審批。
限制
| 限制 | 說明 |
|---|---|
| 只備份 DML 影響的 row,不備份整表 | 例:UPDATE WHERE id=42 只備這一筆,不備整張 users |
| 不備份 SELECT 結果、不備份 view、不備份 sequence | 純 DML 變更感知 |
bbdataarchive 內表沒 retention 政策 | 長期累積會佔空間,需要 DBA 定期清 — SOP 見 bbdataarchive 保留政策 |
| 不能跨 instance / 跨 DB engine | backup 跟 source 必須同 instance |
| 不取代 PITR / DB 內建備份 | 是「逐次變更的 row 級備份」不是「整 DB 時間點還原」 |
DDL 變更:sync_history + Revision(schema 歷史追蹤)
DDL 沒有等同 PriorBackup 的機制 — schema 變更(CREATE TABLE / ALTER COLUMN / DROP COLUMN)很多動作沒有乾淨的反向 SQL:
| DDL | 反向可行嗎 |
|---|---|
ADD COLUMN x INT NULL | ✅ 簡單:DROP COLUMN x |
ADD COLUMN x INT NOT NULL DEFAULT 0 | ⚠️ 反向後,原本沒值的 row 應該怎樣? |
DROP COLUMN x | ❌ 資料已 gone,反向只能拿到空欄位 |
DROP TABLE users | ❌ 整表資料 gone |
ALTER COLUMN type TEXT → VARCHAR(50) | ⚠️ 截斷風險,反向不安全 |
所以 Argus 對 DDL 走「追蹤 + 手動寫反向 SQL」路徑,不嘗試自動生成。
Argus 為你存了什麼
每次 Plan-driven 變更後:
| 表 | 角色 |
|---|---|
revision | 每筆 schema 變更寫一筆,含 version + 完整 SQL(你可以反查上次跑了什麼) |
sync_history | 每次 sync schema 拍一張 metadata snapshot(含 raw_dump) |
changelog | 把 task_run 連到 sync_history,知道「哪次跑了什麼 → 跑完後 schema 是什麼樣」 |
怎麼寫反向 Plan
- 找變更時間點:上 audit log 查
bb.databases.adminExecute或對應 issue 的 TaskRun 時間 - 撈變更前 snapshot:sql
SELECT raw_dump FROM sync_history WHERE instance = '<instance>' AND db_name = '<db>' AND created_at < '<變更時間>' ORDER BY created_at DESC LIMIT 1; - diff 出反向 SQL:用 Atlas /
pg_dump --schema-only/ 手寫,比對「現在 schema」vs「snapshot schema」 - 開新 Plan 跑反向 SQL — 一樣走 advisor + 審批
跟 Schema Drift Detection 的銜接
DDL 反向 Plan 跑完後:
- TaskRun 結束會自動祝福新 baseline(
backend/runner/taskrun/blessing_hook.go) - 下次 Schema Drift runner tick 不再出現該 db 的 drift event
- 如果有殘餘 drift event 未 resolve,Auditor 在列表手動 Resolve 標
retroactive_plan
DML + DDL 混合變更怎麼算
很常見:一個 Plan 內既有 DDL 又有 DML(例:先 ADD COLUMN,再 UPDATE 新欄位)。
| 混合場景 | PriorBackup 行為 |
|---|---|
ALTER TABLE ADD COLUMN; UPDATE ... | TransformDMLToSelect 自動過濾掉 DDL,只備份 UPDATE 影響的 row |
| 純 DDL | 不會生成 backup(但 sync_history 仍會拍 snapshot) |
| 純 DML | 完整 PriorBackup |
反模式 — 看到立刻喊停
| 行為 | 為什麼不該 |
|---|---|
| 直接 connect prod 跑反向 SQL(不開 Plan) | 違反「所有變更走 Plan」;觸發 Schema Drift event |
| 把 bbdataarchive 當長期備份倉 | 它不是 — 只是逐次 PriorBackup 的累積;定期清 |
| 用 PriorBackup 取代 DB 內建 backup / PITR | 兩個維度不同 — PriorBackup 是「逐次變更追溯」,PITR 是「整 DB 時間點還原」。兩者並存 |
| Snowflake / MongoDB 上勾 enablePriorBackup 期待會備份 | 不支援的 engine 會 silently skip |
| 寫反向 Plan 不勾 enablePriorBackup | 反向也是變更,也該備 — 萬一倒帶倒錯方向再想倒帶 |
常見錯誤
| 訊息 / 現象 | 含意 | 處理 |
|---|---|---|
| PRIOR_BACKUP_END 含 error | 備份失敗(通常 sidecar DB 權限不夠 / 空間不足) | 看 error 訊息;通常 DBA 在 instance 內手動建好 bbdataarchive 並 grant 權限 |
| TaskRunLog 沒有 PRIOR_BACKUP_END | 沒勾 enablePriorBackup 或不支援的 engine | 確認 Plan 設定 + engine |
bbdataarchive 內找不到對應 backup table | TaskRun 還在跑或備份失敗中斷 | 看 TaskRunLog;正常完成的 PRIOR_BACKUP_END 一定有 PriorBackupDetail |
| Plan 勾了 enablePriorBackup 但 PriorBackupDetail 是 empty Items | DML 影響 0 row(WHERE 沒匹配任何 row) | 跑前先 SELECT COUNT 確認 |
相關
- 概念:Plan、Issue、Rollout
- 概念:Release 與 Revision
- 概念:Schema Drift Detection
- DBA:Release 與版本回溯
- DBA:用 AdminExecute 緊急直跑 — AdminExecute 不做 PriorBackup
- 部署:備份與災備 — DB 層級的 backup / PITR