# Momentry 備份版本管理規範 | 項目 | 內容 | |------|------| | 建立者 | Warren / OpenCode | | 建立時間 | 2026-03-25 | | 文件版本 | V1.0 | --- ## 版本歷史 | 版本 | 日期 | 目的 | 操作人 | |------|------|------|--------| | V1.0 | 2026-03-25 | 建立備份版本管理規範 | OpenCode | --- ## 1. 概述 本文檔定義 Momentry 系統的備份版本管理規範,確保新舊架構之間的回滾相容性。 ### 1.1 版本定義 | 版本 | 日期 | 說明 | |------|------|------| | v1 | 2026-03-18 | 初始備份架構(不包含新架構組件)| | v2 | 2026-03-25 | 新架構備份(包含 monitor_jobs, processor_results, Output 目錄)| ### 1.2 備份版本格式 | 版本 | 檔案命名格式 | |------|-------------| | v1 | `{service}_{type}_{YYYYMMDD}_{HHMMSS}.{ext}` | | v2 | `{service}_{type}_v2_{YYYYMMDD}_{HHMMSS}.{ext}` | ### 1.3 各版本涵蓋範圍 | 組件 | v1 | v2 | |------|-----|-----| | PostgreSQL (videos, chunks) | ✅ | ✅ | | PostgreSQL (monitor_jobs) | ❌ | ✅ | | PostgreSQL (processor_results) | ❌ | ✅ | | Redis | ✅ | ✅ | | MongoDB Cache | ⚠️ | ⚠️ | | Output (probe.json) | ❌ | ✅ | > ⚠️ MongoDB 備份目前存在路徑問題,正在修復中 --- ## 2. 備份版本識別 ### 2.1 檔名識別 ```bash # 識別版本 detect_version() { local backup_file=$1 if echo "$backup_file" | grep -q "_v2_"; then echo "v2" else echo "v1" fi } # 使用範例 detect_version "postgresql_db_momentry_v2_20260325_030000.sql.gz" # 輸出: v2 detect_version "postgresql_db_momentry_20260324_030000.sql.gz" # 輸出: v1 ``` ### 2.2 內容識別 ```bash # 檢查是否為 v2 備份 is_v2_backup() { local backup_file=$1 gzip -dc "$backup_file" 2>/dev/null | grep -q "monitor_jobs" && echo "yes" || echo "no" } # 檢查是否包含 processor_results has_processor_results() { local backup_file=$1 gzip -dc "$backup_file" 2>/dev/null | grep -q "processor_results" && echo "yes" || echo "no" } ``` ### 2.3 檔案大小比較 | 版本 | PostgreSQL 備份大小 | 說明 | |------|---------------------|------| | v1 | ~18-19 MB | 基本資料表 | | v2 | >19 MB | 包含新表格和索引 | --- ## 3. 回滾策略 ### 3.1 回滾流程圖 ``` ┌─────────────────────────────────────────┐ │ 選擇還原目標 │ └─────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ 選擇備份版本 │ │ ┌───────────┐ ┌───────────┐ │ │ │ v1 備份 │ │ v2 備份 │ │ │ └───────────┘ └───────────┘ │ └─────────────────────────────────────────┘ │ ┌─────────┴─────────┐ ▼ ▼ ┌──────────┐ ┌──────────┐ │ v1 回滾 │ │ v2 回滾 │ └──────────┘ └──────────┘ │ │ ▼ ▼ ┌──────────┐ ┌──────────┐ │ 基本資料庫 │ │ 完整還原 │ └──────────┘ └──────────┘ ``` ### 3.2 回滾矩陣 | 還原目標 | v1 備份 | v2 備份 | |----------|---------|---------| | 基本資料庫 | ✅ | ✅ | | + monitor_jobs | ❌ | ✅ | | + processor_results | ❌ | ✅ | | + Output 檔案 | ❌ | ✅ | | + MongoDB Cache | ⚠️ | ⚠️ | ### 3.3 回滾相容性說明 #### v1 → v2(支援) - v1 備份可以還原到 v2 架構 - 新架構組件會從空白狀態開始 - 不會造成資料損壞 #### v2 → v1(⚠️ 警告) ``` ⚠️ v2 回滾到 v1 可能導致資料丟失 影響範圍: - monitor_jobs 資料會消失 - processor_results 資料會消失 - Output 檔案參照可能失效 建議: 1. 在還原前建立 v2 快照 2. 或使用隔離還原(staging restore) ``` --- ## 4. 還原腳本保護機制 ### 4.1 還原前檢查 ```bash # 還原前檢查版本相容性 pre_restore_check() { local backup_file=$1 local version=$(detect_version "$backup_file") local current_db_version=$(check_current_db_version) echo "備份版本: $version" echo "目前版本: $current_db_version" # v2 → v1: 警告但允許(使用者需確認) if [ "$version" = "v1" ] && [ "$current_db_version" = "v2" ]; then echo "⚠️ 警告:即將回滾到 v1" echo "影響:monitor_jobs 和 processor_results 資料將被清除" read -p "確認繼續?(y/N): " confirm [ "$confirm" != "y" ] && exit 1 fi # v1 → v2: 直接允許 if [ "$version" = "v1" ] && [ "$current_db_version" = "v2" ]; then echo "ℹ️ 提示:新架構組件將重新初始化" fi # v2 → v2: 直接允許 # v1 → v1: 直接允許 } ``` ### 4.2 隔離還原(Staging Restore) ```bash # 只還原到暫存資料庫,不影響生產 restore_to_staging() { local backup_file=$1 local version=$(detect_version "$backup_file") echo "執行隔離還原..." echo "版本: $version" # 建立暫存資料庫 PGPASSWORD="$PG_PASSWORD" psql -U "$PG_USER" -d postgres << EOF DROP DATABASE IF EXISTS momentry_staging; CREATE DATABASE momentry_staging; EOF # 還原到暫存資料庫 PGPASSWORD="$PG_PASSWORD" pg_restore -U "$PG_USER" -d "momentry_staging" \ --no-owner --no-acl "$backup_file" echo "✅ 還原完成:momentry_staging" echo "驗證命令:psql -U accusys -d momentry_staging -c '\\dt'" } ``` ### 4.3 版本驗證命令 ```bash # 識別所有備份版本 ls /Users/accusys/momentry/backup/daily/postgresql/*.sql.gz | \ xargs -I {} sh -c 'echo "{}: $(detect_version {})"' # 驗證 v2 備份內容 verify_v2_backup() { local backup_file=$1 echo "驗證備份: $backup_file" # 檢查 monitor_jobs if gzip -dc "$backup_file" | grep -q "monitor_jobs"; then echo "✅ 包含 monitor_jobs" else echo "❌ 缺少 monitor_jobs" return 1 fi # 檢查 processor_results if gzip -dc "$backup_file" | grep -q "processor_results"; then echo "✅ 包含 processor_results" else echo "❌ 缺少 processor_results" return 1 fi echo "✅ v2 備份驗證通過" } ``` --- ## 5. 版本遷移 ### 5.1 v1 → v2 遷移步驟 | 步驟 | 說明 | 驗證 | |------|------|------| | 1 | 確認所有 v1 備份已完成 | `ls *.sql.gz \| grep -v v2` | | 2 | 修改 `backup_all.sh` 加入 v2 標記 | 確認 TIMESTAMP 包含 `v2_` | | 3 | 修正 MongoDB 路徑 | 確認指向正確目錄 | | 4 | 新增 Output 目錄備份 | 確認 probe.json 被備份 | | 5 | 執行測試備份 | 驗證命名格式正確 | | 6 | 驗證 v2 備份完整性 | `verify_v2_backup` | | 7 | 正式啟用 v2 備份 | 確認 crontab 使用新版 | ### 5.2 遷移驗證清單 ```bash #!/bin/bash # verify_v2_migration.sh echo "=== v2 遷移驗證 ===" # 1. 檢查備份腳本 echo "1. 檢查備份腳本..." if grep -q "v2_" /Users/accusys/momentry/scripts/backup_all.sh; then echo " ✅ 版本標記已啟用" else echo " ❌ 版本標記未啟用" fi # 2. 檢查 MongoDB 路徑 echo "2. 檢查 MongoDB 路徑..." if grep -q "/opt/homebrew/var/mongodb" /Users/accusys/momentry/scripts/backup_all.sh; then echo " ✅ MongoDB 路徑已修正" else echo " ❌ MongoDB 路徑未修正" fi # 3. 檢查 Output 目錄備份 echo "3. 檢查 Output 目錄備份..." if grep -q "momentry_output" /Users/accusys/momentry/scripts/backup_all.sh; then echo " ✅ Output 目錄備份已啟用" else echo " ❌ Output 目錄備份未啟用" fi # 4. 檢查最新備份 echo "4. 檢查最新備份..." latest_backup=$(ls -t /Users/accusys/momentry/backup/daily/postgresql/*.sql.gz 2>/dev/null | head -1) if [ -n "$latest_backup" ]; then version=$(detect_version "$latest_backup") echo " 最新備份: $(basename $latest_backup)" echo " 版本: $version" if [ "$version" = "v2" ]; then verify_v2_backup "$latest_backup" fi fi echo "=== 驗證完成 ===" ``` --- ## 6. 疑難排解 ### 6.1 常見問題 | 問題 | 原因 | 解決方案 | |------|------|----------| | 無法識別版本 | 檔名被修改 | 使用內容分析 `gzip -dc \| grep "monitor_jobs"` | | v2 備份還原失敗 | 磁碟空間不足 | 清理空間後重試 | | v1 還原覆蓋 v2 | 操作失誤 | 使用隔離還原保護生產資料 | | MongoDB 備份為空 | 路徑錯誤 | 修正為 `/opt/homebrew/var/mongodb` | ### 6.2 緊急回滾流程 ```bash #!/bin/bash # emergency_restore.sh set -e BACKUP_FILE=$1 VERSION=$2 echo "=== 緊急回滾 ===" echo "備份檔案: $BACKUP_FILE" echo "目標版本: $VERSION" # 1. 建立當前狀態快照 echo "1. 建立當前狀態快照..." NOW=$(date +%Y%m%d_%H%M%S) pg_dump -U accusys -d momentry | gzip > "/tmp/momentry_emergency_$NOW.sql.gz" echo " 快照: /tmp/momentry_emergency_$NOW.sql.gz" # 2. 執行還原 echo "2. 執行還原..." gunzip -c "$BACKUP_FILE" | psql -U accusys -d momentry # 3. 驗證 echo "3. 驗證還原..." psql -U accusys -d momentry -c "SELECT COUNT(*) FROM monitor_jobs;" echo "=== 回滾完成 ===" ``` --- ## 7. 備份清單(v2) ### 7.1 每日備份(v2 格式) | 服務 | 備份項目 | 檔案命名 | 說明 | |------|----------|----------|------| | PostgreSQL | momentry | `postgresql_db_momentry_v2_{date}_{time}.sql.gz` | 完整資料庫 | | PostgreSQL | video_register | `postgresql_db_video_register_v2_{date}_{time}.sql.gz` | 影片註冊資料 | | Redis | RDB | `redis_rdb_v2_{date}_{time}.rdb` | Redis 快照 | | MongoDB | 資料 | `mongodb_data_v2_{date}_{time}.tar.gz` | MongoDB 資料 | | n8n | 資料+DB | `n8n_{date}_{time}.tar.gz`, `n8n_db_{date}_{time}.sql.gz` | n8n 完整 | | SFTPGo | 配置+DB | `sftpgo_{date}_{time}.tar.gz`, `sftpgo_db_{date}_{time}.sql.gz` | SFTPGo | | Gitea | 資料 | `gitea_{date}_{time}.tar.gz` | Gitea | | Output | 檔案 | `momentry_output_v2_{date}_{time}.tar.gz` | probe.json 等 | ### 7.2 備份保留策略 | 類型 | 保留期限 | 位置 | |------|----------|------| | 每日備份 | 7 天 | `backup/daily/` | | 每週備份 | 4 週 | `backup/weekly/` | | 每月備份 | 12 個月 | `backup/monthly/` | | 歸檔 | 1 年+ | `backup/archive/` | --- ## 8. 相關文件 | 文件 | 說明 | |------|------| | [SERVICES.md](./SERVICES.md) | 服務說明 | | [MOMENTRY_CORE_MONITORING.md](./MOMENTRY_CORE_MONITORING.md) | 監控規範 | | `/Users/accusys/momentry/scripts/backup_all.sh` | 備份腳本 | | `/Users/accusys/momentry/scripts/restore_all.sh` | 還原腳本 | | `/Users/accusys/momentry_core_0.1/monitor/storage/backup_monitor.sh` | 備份監控 | --- ## 附錄 A:v2 備份完整性檢查清單 ```bash #!/bin/bash # check_v2_integrity.sh BACKUP_DIR="/Users/accusys/momentry/backup/daily" echo "=== v2 備份完整性檢查 ===" # 檢查 PostgreSQL echo "1. PostgreSQL..." pg_backup=$(ls -t "$BACKUP_DIR/postgresql"/postgresql_db_momentry_v2_*.sql.gz 2>/dev/null | head -1) if [ -n "$pg_backup" ]; then echo " 備份: $(basename $pg_backup)" verify_v2_backup "$pg_backup" else echo " ❌ 未找到 v2 備份" fi # 檢查 Output echo "2. Output 目錄..." output_backup=$(ls -t "$BACKUP_DIR/momentry"/momentry_output_v2_*.tar.gz 2>/dev/null | head -1) if [ -n "$output_backup" ]; then echo " 備份: $(basename $output_backup)" echo " ✅ Output 備份已存在" else echo " ❌ 未找到 Output 備份" fi # 檢查 MongoDB echo "3. MongoDB..." mongo_backup=$(ls -t "$BACKUP_DIR/mongodb"/mongodb_data_v2_*.tar.gz 2>/dev/null | head -1) if [ -n "$mongo_backup" ]; then size=$(stat -f%z "$mongo_backup" 2>/dev/null || stat -c%s "$mongo_backup" 2>/dev/null) echo " 備份: $(basename $mongo_backup)" echo " 大小: $size bytes" if [ "$size" -gt 1000 ]; then echo " ✅ MongoDB 備份有效" else echo " ⚠️ MongoDB 備份可能為空" fi else echo " ❌ 未找到 MongoDB 備份" fi echo "=== 檢查完成 ===" ```