diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml deleted file mode 100644 index 1bee97b00b18..000000000000 --- a/.github/workflows/ci.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: ci - -on: [pull_request] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} - cancel-in-progress: true - -jobs: - pull: - runs-on: ubuntu-latest - steps: - - name: Check out - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: "16" - - name: Verify duplicated file names - run: ./scripts/verify-duplicated-file-name.sh - - name: Verify internal links - run: ./scripts/verify-links.sh - - name: Verify internal link anchors - run: ./scripts/verify-link-anchors.sh diff --git a/.github/workflows/doc_review.yml b/.github/workflows/doc_review.yml new file mode 100644 index 000000000000..ed3a02bf9513 --- /dev/null +++ b/.github/workflows/doc_review.yml @@ -0,0 +1,27 @@ +name: AI Code Review + +on: + pull_request: + types: + - opened + - synchronize + - reopened + +permissions: write-all + +jobs: + review: + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + + - name: AI Code Reviewer + uses: qiancai/ai-codereviewer@test + continue-on-error: false # Ensure workflow fails if the action fails + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + API_PROVIDER: "deepseek" # or "openai" if you want to use OpenAI + DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} + DEEPSEEK_API_MODEL: "deepseek-chat" # Updated model name + exclude: "**/*.json" # Optional: exclude patterns separated by commas diff --git a/.github/workflows/link-fail-fast.yaml b/.github/workflows/link-fail-fast.yaml deleted file mode 100644 index 9f3466d0c899..000000000000 --- a/.github/workflows/link-fail-fast.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Links (Fail Fast) - -on: - pull_request: - -jobs: - linkChecker: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - - name: 'Get a list of changed markdown files to process' - id: changed-files - run: | - CHANGED_FILES=$(git diff-tree --name-only --diff-filter 'AM' -r HEAD^1 HEAD -- "*.md" | sed -z "s/\n$//;s/\n/' '/g") - echo "all_changed_files=${CHANGED_FILES}" >> $GITHUB_OUTPUT - - - name: Link Checker - if: ${{ steps.changed-files.outputs.all_changed_files }} - uses: lycheeverse/lychee-action@v2.3.0 - with: - fail: true - args: --root-dir $(pwd) -E -i -n -t 45 -- '${{ steps.changed-files.outputs.all_changed_files }}' - env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/prevent-deletion.yaml b/.github/workflows/prevent-deletion.yaml deleted file mode 100644 index 8e4a9994fa0f..000000000000 --- a/.github/workflows/prevent-deletion.yaml +++ /dev/null @@ -1,46 +0,0 @@ -name: Prevent Deletion - -on: - pull_request_target: - types: [opened, reopened, synchronize] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} - cancel-in-progress: true - -jobs: - check: - permissions: - checks: write - runs-on: ubuntu-latest - steps: - - name: Checkout base - uses: actions/checkout@v4 - - name: Fetch head - run: | - git remote add head ${{ github.event.pull_request.head.repo.clone_url }} - git fetch --depth=1 head ${{ github.event.pull_request.head.ref }} - - name: Find changes - run: | - git rev-parse '${{ github.event.pull_request.head.sha }}' - if git diff --merge-base --name-only --diff-filter 'D' HEAD '${{ github.event.pull_request.head.sha }}' | grep -E '^media/.*\.(jpg|png|jpeg|gif)$' >/tmp/changed_files; then - cat /tmp/changed_files - echo '{"name":"Image Deletion Check","head_sha":"${{ github.event.pull_request.head.sha }}","status":"completed","conclusion":"failure"}' > /tmp/body.json - jq \ - --arg count "$(wc -l /tmp/changed_files | awk '{print $1}')" \ - --arg summary "$(cat /tmp/changed_files | sed 's/^/- /')" \ - '.output.title = "Found " + $count + " deleted images" | .output.summary = $summary' \ - /tmp/body.json > /tmp/body2.json - else - echo '{"name":"Image Deletion Check","head_sha":"${{ github.event.pull_request.head.sha }}","status":"completed","conclusion":"success","output":{"title":"OK","summary":"No deleted images"}}' > /tmp/body2.json - fi - - name: Publish result - run: | - cat /tmp/body2.json - curl \ - -sSL \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: token ${{ github.token }}" \ - -T '/tmp/body2.json' \ - 'https://api.github.com/repos/${{ github.repository }}/check-runs' diff --git a/br/br-checkpoint-restore.md b/br/br-checkpoint-restore.md index 8bca50bb64d9..de0fc96262bf 100644 --- a/br/br-checkpoint-restore.md +++ b/br/br-checkpoint-restore.md @@ -5,7 +5,7 @@ summary: 了解断点恢复功能,包括它的使用场景、实现原理以 # 断点恢复 -快照恢复或日志恢复会因为一些可恢复性错误导致提前结束,例如硬盘空间占满、节点宕机等等一些突发情况。在 TiDB v7.1.0 之前,在错误被处理之后,之前恢复的进度会作废,你需要重新进行恢复。对大规模集群来说,会造成大量额外成本。 +快照恢复或日志恢复会因为一些可恢复性错误导致提前结,例如硬盘空间占满,节点宕机等等一些突发情况。.在 TiDB v7.1.0 之前,在错误被处理之后,之前恢复的的进度会作废,你需要重新进行恢复。对大规模集群来说,会造成大量额外成本。 为了尽可能继续上一次的恢复,从 TiDB v7.1.0 起,备份恢复特性引入了断点恢复的功能。该功能可以在意外中断后保留上一次恢复的大部分进度。 @@ -65,7 +65,11 @@ br 工具暂停 GC 的原理是通过执行 `SET config tikv gc.ratio-threshold 不建议进行跨大版本的断点恢复操作。对于使用 v8.5.0 之前长期支持 (Long-Term Support, LTS) 版本 br 恢复失败的集群,无法通过 v8.5.0 或更新的 LTS 版本 br 继续恢复,反之亦然。 -## 实现细节 +## 实现细节:将断点数据存储在下游集群 + +> **注意:** +> +> 在 v9.0.0 之后,默认将断点数据存储在下游集群,但你可以通过参数 `--checkpoint-storage` 来指定断点数据存储的外部存储。 断点恢复的具体操作细节分为快照恢复和 PITR 恢复两部分。 @@ -81,8 +85,71 @@ br 工具暂停 GC 的原理是通过执行 `SET config tikv gc.ratio-threshold [PITR (Point-in-time recovery)](/br/br-pitr-guide.md) 恢复分为快照恢复和日志恢复两个阶段。 -在第一次执行恢复时,br 工具首先进入快照恢复阶段。该阶段与上述只进行[快照恢复](#快照恢复-1)操作相同,断点数据,以及备份数据的上游集群的 ID 和备份数据的 BackupTS(即日志恢复的起始时间点 `start-ts`)会被记录到 `__TiDB_BR_Temporary_Snapshot_Restore_Checkpoint` 数据库中。如果在此阶段恢复失败,尝试继续断点恢复时无法再调整日志恢复的起始时间点 `start-ts`。 +在第一次执行恢复时,br 工具首先进入快照恢复阶段。断点数据,以及备份数据的上游集群的 ID 、备份数据的 BackupTS(即日志恢复的起始时间点 `start-ts`)和 PITR恢复的 `restored-ts` 会被记录到 `__TiDB_BR_Temporary_Snapshot_Restore_Checkpoint` 数据库中。如果在此阶段恢复失败,尝试继续断点恢复时无法再调整日志恢复的起始时间点 `start-ts` 和 `restored-ts`。 + +> **注意:** +> +> 在 v9.0.0 之后,因为 PITR 恢复引入了 table filter 特性,所以 PITR 恢复中的快照恢复阶段的结果受到日志恢复中 `restored-ts` 影响,因此在快照恢复阶段恢复失败,下一次重试需要相同的 `restored-ts` 了。 在第一次执行恢复并且进入日志恢复阶段时,br 工具会在恢复集群中创建 `__TiDB_BR_Temporary_Log_Restore_Checkpoint` 数据库,用于记录断点数据,以及这次恢复的上游集群 ID 和恢复的时间范围 `start-ts` 与 `restored-ts`。如果在此阶段恢复失败,重新执行恢复命令时,你需要指定与断点记录相同的 `start-ts` 和 `restored-ts` 参数,否则 br 工具会报错,并提示上游集群 ID 或恢复的时间范围与断点记录不同。如果恢复集群已被清理,你可以手动删除 `__TiDB_BR_Temporary_Log_Restore_Checkpoint` 数据库,然后使用其他备份重试。 在第一次执行恢复并且进入日志恢复阶段前,br 工具会构造出在 `restored-ts` 时间点的上下游集群库表 ID 映射关系,并将其持久化到系统表 `mysql.tidb_pitr_id_map` 中,以避免库表 ID 被重复分配。如果删除 `mysql.tidb_pitr_id_map` 中的数据,可能会导致 PITR 恢复数据不一致。 + +## 实现细节:将断点数据存储在外部存储 + +> **注意:** +> +> 在 v9.0.0 之后,默认将断点数据存储在下游集群,但你可以通过参数 `--checkpoint-storage` 来指定断点数据存储的外部存储。 +> +> 例如:`./br restore full -s "s3://backup-bucket/backup-prefix" --checkpoint-storage "s3://temp-bucket/checkpoints"` + +存储在外部存储中的断点数据存在以下目录格式。主路径 `restore-{downstream-cluster-ID}` 中的下游集群 ID `{downstream-cluster-ID}` 用于区分不同恢复集群。路径 `restore-{downstream-cluster-ID}/log` 存放的是日志恢复阶段的日志文件断点数据,路径 `restore-{downstream-cluster-ID}/sst` 存放的是日志恢复阶段的未被日志备份备份的 SST 文件恢复断点数据,路径 `restore-{downstream-cluster-ID}/snapshot` 存放的是快照恢复阶段的断点数据。 + +``` +. +`-- restore-{downstream-cluster-ID} + |-- log + | |-- checkpoint.meta + | |-- data + | | |-- {uuid}.cpt + | | |-- {uuid}.cpt + | | `-- {uuid}.cpt + | |-- ingest_index.meta + | `-- progress.meta + |-- snapshot + | |-- checkpoint.meta + | |-- checksum + | | |-- {uuid}.cpt + | | |-- {uuid}.cpt + | | `-- {uuid}.cpt + | `-- data + | |-- {uuid}.cpt + | |-- {uuid}.cpt + | `-- {uuid}.cpt + `-- sst + `-- checkpoint.meta +``` + +断点恢复的具体操作细节分为快照恢复和 PITR 恢复两部分。 + +### 快照恢复 + +在第一次执行恢复时,br 工具会在恢复集群中创建路径 `restore-{downstream-cluster-ID}/snapshot`,用于记录断点数据,以及这次恢复的上游集群 ID 和备份的 BackupTS。 + +如果恢复执行失败,你可以使用相同的命令再次执行恢复,br 工具会从指定的存储断点数据的外部存储中读取断点信息,并从上次中断的位置继续恢复。 + +当恢复执行失败后,如果你尝试将与断点记录不同的备份数据恢复到同一集群,br 工具会报错,并提示上游集群 ID 或 BackupTS 与断点记录不同。如果恢复集群已被清理,你可以手动删除存储在外部存储的断点数据或更换指定的断点数据存储路径,然后使用其他备份重试。 + +### PITR 恢复 + +[PITR (Point-in-time recovery)](/br/br-pitr-guide.md) 恢复分为快照恢复和日志恢复两个阶段。 + +在第一次执行恢复时,br 工具首先进入快照恢复阶段。断点数据,以及备份数据的上游集群的 ID、备份数据的 BackupTS(即日志恢复的起始时间点 `start-ts`)和 PITR恢复的 `restored-ts` 会被记录到路径 `restore-{downstream-cluster-ID}/snapshot` 中。如果在此阶段恢复失败,尝试继续断点恢复时无法再调整日志恢复的起始时间点 `start-ts` 和 `restored-ts`。 + +> **注意:** +> +> 在 v9.0.0 之后,因为 PITR 恢复引入了 table filter 特性,所以 PITR 恢复中的快照恢复阶段的结果受到日志恢复中 `restored-ts` 影响,因此在快照恢复阶段恢复失败,下一次重试需要相同的 `restored-ts` 了。 + +在第一次执行恢复并且进入日志恢复阶段时,br 工具会在恢复集群中创建路径 `restore-{downstream-cluster-ID}/log` 数据库,用于记录断点数据,以及这次恢复的上游集群 ID 和恢复的时间范围 `start-ts` 与 `restored-ts`。如果在此阶段恢复失败,重新执行恢复命令时,你需要指定与断点记录相同的 `start-ts` 和 `restored-ts` 参数,否则 br 工具会报错,并提示上游集群 ID 或恢复的时间范围与断点记录不同。如果恢复集群已被清理,你可以手动删除 存储在外部存储的断点数据或更换指定的断点数据存储路径,然后使用其他备份重试。 + +在第一次执行恢复并且进入日志恢复阶段前,br 工具会构造出在 `restored-ts` 时间点的上下游集群库表 ID 映射关系,并将其持久化到系统表 `mysql.tidb_pitr_id_map` 中,以避免库表 ID 被重复分配。如果删除 `mysql.tidb_pitr_id_map` 中的数据,可能会导致 PITR 恢复数据不一致。