备份与恢复 #

一、备份概述 #

1.1 备份策略 #

text
FaunaDB备份方式:
├── 导出/导入
│   └── 数据导出为JSON
├── 时间旅行
│   └── 利用历史数据恢复
├── 副本数据库
│   └── 创建数据库副本
└── 外部备份
    └── 导出到外部存储

1.2 备份考虑 #

text
备份规划:
├── 备份频率
├── 保留周期
├── 存储位置
├── 恢复时间目标(RTO)
└── 恢复点目标(RPO)

二、数据导出 #

2.1 使用CLI导出 #

bash
# 导出整个数据库
fauna export my_database --output=./backup

# 导出特定集合
fauna export my_database --collections=users,products --output=./backup

# 导出为JSON格式
fauna export my_database --format=json --output=./backup

2.2 使用FQL导出 #

javascript
// 导出集合数据
Map(
  Paginate(Documents(Collection("users")), { size: 10000 }),
  Lambda("ref", Get(Var("ref")))
)

// 导出特定字段
Map(
  Paginate(Documents(Collection("users"))),
  Lambda("ref",
    Let(
      { doc: Get(Var("ref")) },
      {
        id: Select(["ref", "id"], Var("doc")),
        name: Select(["data", "name"], Var("doc")),
        email: Select(["data", "email"], Var("doc"))
      }
    )
  )
)

2.3 导出脚本 #

javascript
// 分页导出大数据量
CreateFunction({
  name: "export_collection",
  role: Role("admin"),
  body: Query(
    Lambda(["collectionName", "pageSize"],
      Let(
        {
          pages: Query(
            Lambda("cursor",
              Let(
                {
                  page: If(
                    Equals(Var("cursor"), null),
                    Paginate(
                      Documents(Collection(Var("collectionName"))),
                      { size: Var("pageSize") }
                    ),
                    Paginate(
                      Documents(Collection(Var("collectionName"))),
                      {
                        size: Var("pageSize"),
                        after: Var("cursor")
                      }
                    )
                  )
                },
                {
                  data: Map(
                    Select(["data"], Var("page")),
                    Lambda("ref", Get(Var("ref")))
                  ),
                  nextCursor: If(
                    ContainsPath(Var("page"), ["after"]),
                    Select(["after"], Var("page")),
                    false
                  )
                }
              )
            )
          )
        },
        Var("pages")
      )
    )
  )
})

三、数据导入 #

3.1 使用CLI导入 #

bash
# 导入数据
fauna import my_database --file=./backup/users.json

# 导入到特定集合
fauna import my_database --collection=users --file=./backup/users.json

# 更新模式(更新已存在的文档)
fauna import my_database --file=./backup/users.json --mode=update

3.2 使用FQL导入 #

javascript
// 批量导入
Foreach(
  [
    { name: "User 1", email: "user1@example.com" },
    { name: "User 2", email: "user2@example.com" },
    { name: "User 3", email: "user3@example.com" }
  ],
  Lambda("userData",
    Create(Collection("users"), {
      data: Var("userData")
    })
  )
)

3.3 导入函数 #

javascript
// 创建导入函数
CreateFunction({
  name: "import_data",
  role: Role("admin"),
  body: Query(
    Lambda(["collectionName", "data"],
      Foreach(
        Var("data"),
        Lambda("item",
          Create(Collection(Var("collectionName")), {
            data: Var("item")
          })
        )
      )
    )
  )
})

// 调用导入
Call(Function("import_data"), ["users", [
  { name: "User 1", email: "user1@example.com" },
  { name: "User 2", email: "user2@example.com" }
]])

四、数据库复制 #

4.1 创建副本数据库 #

javascript
// 创建备份数据库
CreateDatabase({
  name: "my_database_backup"
})

// 复制数据
Let(
  {
    sourceCollection: Collection("users"),
    targetCollection: Collection("users", Database("my_database_backup"))
  },
  Foreach(
    Paginate(Documents(Var("sourceCollection"))),
    Lambda("ref",
      Let(
        { doc: Get(Var("ref")) },
        Create(Var("targetCollection"), {
          data: Select(["data"], Var("doc"))
        })
      )
    )
  )
)

4.2 增量同步 #

javascript
// 增量同步函数
CreateFunction({
  name: "sync_collection",
  role: Role("admin"),
  body: Query(
    Lambda(["sourceDb", "targetDb", "collectionName", "lastSyncTime"],
      Let(
        {
          sourceColl: Collection(Var("collectionName"), Database(Var("sourceDb"))),
          targetColl: Collection(Var("collectionName"), Database(Var("targetDb"))),
          
          // 获取变更的文档
          changedDocs: Filter(
            Paginate(Documents(Var("sourceColl"))),
            Lambda("ref",
              GT(
                Select(["ts"], Get(Var("ref"))),
                Var("lastSyncTime")
              )
            )
          )
        },
        Foreach(
          Var("changedDocs"),
          Lambda("ref",
            Let(
              {
                doc: Get(Var("ref")),
                docId: Select(["ref", "id"], Var("doc")),
                targetRef: Ref(Var("targetColl"), Var("docId"))
              },
              If(
                Exists(Var("targetRef")),
                Update(Var("targetRef"), {
                  data: Select(["data"], Var("doc"))
                }),
                Create(Var("targetRef"), {
                  data: Select(["data"], Var("doc"))
                })
              )
            )
          )
        )
      )
    )
  )
})

五、时间旅行恢复 #

5.1 恢复到历史时间点 #

javascript
// 恢复单个文档
Let(
  {
    ref: Ref(Collection("users"), "user_001"),
    targetTime: Time("2024-01-15T00:00:00Z"),
    historicalDoc: Get(Var("ref"), Var("targetTime"))
  },
  Update(Var("ref"), {
    data: Select(["data"], Var("historicalDoc"))
  })
)

5.2 批量历史恢复 #

javascript
// 批量恢复
Let(
  {
    targetTime: Time("2024-01-01T00:00:00Z"),
    refs: Paginate(Documents(Collection("products")))
  },
  Foreach(
    Var("refs"),
    Lambda("ref",
      Let(
        {
          historicalDoc: Get(Var("ref"), Var("targetTime"))
        },
        Update(Var("ref"), {
          data: Select(["data"], Var("historicalDoc"))
        })
      )
    )
  )
)

六、灾难恢复 #

6.1 恢复流程 #

text
灾难恢复步骤:
├── 1. 评估损失范围
├── 2. 确定恢复时间点
├── 3. 创建临时数据库
├── 4. 导入备份数据
├── 5. 验证数据完整性
├── 6. 切换应用连接
└── 7. 监控恢复状态

6.2 恢复脚本 #

javascript
// 完整恢复函数
CreateFunction({
  name: "disaster_recovery",
  role: Role("admin"),
  body: Query(
    Lambda(["targetDb", "backupData", "collections"],
      Let(
        {
          db: Database(Var("targetDb")),
          result: Map(
            Var("collections"),
            Lambda("collName",
              Let(
                {
                  coll: Collection(Var("collName"), Var("db")),
                  data: Select(Var("collName"), Var("backupData"))
                },
                {
                  collection: Var("collName"),
                  imported: Count(
                    Foreach(
                      Var("data"),
                      Lambda("item",
                        Create(Var("coll"), { data: Var("item") })
                      )
                    )
                  )
                }
              )
            )
          )
        },
        {
          status: "completed",
          timestamp: Now(),
          details: Var("result")
        }
      )
    )
  )
})

七、备份自动化 #

7.1 定时备份 #

javascript
// 创建备份记录
CreateFunction({
  name: "create_backup_record",
  role: Role("admin"),
  body: Query(
    Lambda(["type", "collections", "status"],
      Create(Collection("backup_records"), {
        data: {
          type: Var("type"),
          collections: Var("collections"),
          status: Var("status"),
          timestamp: Now(),
          size: 0,
          location: ""
        }
      })
    )
  )
})

7.2 备份验证 #

javascript
// 验证备份完整性
CreateFunction({
  name: "verify_backup",
  role: Role("admin"),
  body: Query(
    Lambda("backupId",
      Let(
        {
          backup: Get(Ref(Collection("backup_records"), Var("backupId"))),
          collections: Select(["data", "collections"], Var("backup")),
          
          verification: Map(
            Var("collections"),
            Lambda("collName",
              Let(
                {
                  sourceCount: Count(Documents(Collection(Var("collName")))),
                  // 假设备份存储了计数
                  backupCount: Select(
                    ["data", "counts", Var("collName")],
                    Var("backup"),
                    0
                  )
                },
                {
                  collection: Var("collName"),
                  source: Var("sourceCount"),
                  backup: Var("backupCount"),
                  valid: Equals(Var("sourceCount"), Var("backupCount"))
                }
              )
            )
          )
        },
        {
          backupId: Var("backupId"),
          timestamp: Now(),
          results: Var("verification"),
          allValid: All(
            Map(Var("verification"), Lambda("v", Select("valid", Var("v"))))
          )
        }
      )
    )
  )
})

八、最佳实践 #

8.1 备份策略 #

text
备份策略建议:
├── 定期备份(每日/每周)
├── 多重备份(本地+远程)
├── 版本化备份
├── 加密敏感数据
└── 测试恢复流程

8.2 备份保留 #

text
保留策略:
├── 每日备份:保留7天
├── 每周备份:保留4周
├── 每月备份:保留12个月
└── 年度备份:长期保留

8.3 安全考虑 #

text
安全建议:
├── 加密备份数据
├── 限制备份访问权限
├── 安全存储备份凭证
├── 审计备份操作
└── 定期更新加密密钥

九、实际应用示例 #

9.1 完整备份系统 #

javascript
// 创建完整备份系统
CreateFunction({
  name: "full_backup",
  role: Role("admin"),
  body: Query(
    Lambda("databaseName",
      Let(
        {
          db: Database(Var("databaseName")),
          collections: Select(
            ["data"],
            Paginate(Collections(), { size: 100 })
          ),
          timestamp: Now(),
          
          backup: Map(
            Var("collections"),
            Lambda("collRef",
              Let(
                {
                  collName: Select(["id"], Var("collRef")),
                  docs: Map(
                    Paginate(
                      Documents(Var("collRef")),
                      { size: 10000 }
                    ),
                    Lambda("ref", Get(Var("ref")))
                  )
                },
                {
                  collection: Var("collName"),
                  count: Count(Var("docs")),
                  data: Var("docs")
                }
              )
            )
          ),
          
          // 创建备份记录
          record: Create(Collection("backup_records"), {
            data: {
              database: Var("databaseName"),
              timestamp: Var("timestamp"),
              type: "full",
              status: "completed",
              collections: Map(
                Var("backup"),
                Lambda("b", Select("collection", Var("b")))
              ),
              counts: Map(
                Var("backup"),
                Lambda("b",
                  {
                    collection: Select("collection", Var("b")),
                    count: Select("count", Var("b"))
                  }
                )
              )
            }
          })
        },
        {
          backupId: Select(["ref", "id"], Var("record")),
          timestamp: Var("timestamp"),
          summary: Map(
            Var("backup"),
            Lambda("b",
              {
                collection: Select("collection", Var("b")),
                documents: Select("count", Var("b"))
              }
            )
          )
        }
      )
    )
  )
})

十、总结 #

备份与恢复要点:

方法 说明
CLI导出 使用fauna命令行
FQL导出 使用查询导出
数据库复制 创建副本数据库
时间旅行 利用历史数据
自动化 定时备份脚本

下一步,让我们学习性能优化!

最后更新:2026-03-27