当前位置:首页 > 文章列表 > 文章 > python教程 > Python sqlite3 备份进度回调怎样判断剩余页数

Python sqlite3 备份进度回调怎样判断剩余页数

来源:17golang原创 2026-10-09 09:59:53 0浏览 收藏

sqlite3.Connection.backup() 的进度回调不需要自己查询数据库大小:回调第二个参数 remaining 就是仍待复制的 SQLite 页数,第三个参数 total 是总页数。已复制页数可用 total - remaining 计算,完成百分比是 (total - remaining) / total * 100。第一个参数 status 则表示最近一次备份迭代的 SQLite 状态码。

官方文档:https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.backup

日常开发你可以先理清这几个要点
  • remaining 的单位是数据库页,不是行、字节或秒。
  • pages 决定每次迭代最多复制多少页,但最后一轮可能少于这个值。
  • remaining == 0 表示没有剩余页;结合 status == sqlite3.SQLITE_DONE 可识别完成迭代。
  • 源库被并发写入时,底层备份可能重启,remaining 可能回升,不能假定进度永远单调。

基线数据:progress 回调直接给出剩余页数

Python 文档给出的签名是 backup(target, *, pages=-1, progress=None, name='main', sleep=0.250)。只要把可调用对象传给 progress,每次备份迭代后就会收到三个整数:

参数含义适合监控的指标
status最近一次迭代的 SQLite 状态码复制中、完成或异常状态
remaining还需要复制的页面数剩余工作量
total源数据库总页面数进度分母

例如某次回调收到 remaining=768、total=1024,那么已复制 256 页,完成度为 25%。这是公式演示,不是某台机器的性能实测。

Python sqlite3 在线备份从源连接经 backup 迭代到目标连接,并把 status、remaining、total 交给进度回调的静态结构图
图1:备份迭代负责复制页面,progress 回调只接收最近一次迭代的状态与页面计数。

假设与公式:怎样从回调值算出四个指标

最稳妥的指标是“剩余页数”和“完成比例”。如果还想知道本次回调推进了多少页,需要保存上一次的 remaining:

指标计算方法注意点
剩余页数remaining回调已直接提供
已复制页数max(total - remaining, 0)不要用回调次数乘 pages
完成比例copied / total * 100先处理 total 为 0 的情况
本轮推进页数previous_remaining - remaining并发写入导致 remaining 回升时应视为重启或重新计数

“回调次数 × pages”不可靠:最后一轮可能不足 pages,锁竞争可能产生没有推进页面的迭代,并发写入还可能触发底层备份重启。

改动点:实现一个可复用的进度记录器

下面的记录器同时输出状态码、已复制页数、剩余页数、比例、单轮增量和耗时。它发现 remaining 比上次更大时,不再给出负数增量,而是标记为“重新计数”。

import sqlite3
import time


class BackupProgress:
    def __init__(self):
        # 使用单调时钟统计经过时间,避免系统时间调整干扰。
        self.started_at = time.monotonic()
        self.previous_remaining = None

    def __call__(self, status, remaining, total):
        # remaining 由回调直接提供;copied 不能用回调次数乘 pages 推算。
        copied = max(total - remaining, 0)
        percent = copied / total * 100 if total > 0 else 100.0

        restarted = (
            self.previous_remaining is not None
            and remaining > self.previous_remaining
        )
        if self.previous_remaining is None:
            step_pages = copied
        elif restarted:
            # 源库并发写入可能让备份重启,此时不输出负的批次增量。
            step_pages = 0
        else:
            step_pages = self.previous_remaining - remaining

        done_code = getattr(sqlite3, "SQLITE_DONE", 101)
        phase = "完成" if status == done_code and remaining == 0 else "复制中"
        elapsed = time.monotonic() - self.started_at
        restart_note = ",检测到重新计数" if restarted else ""

        print(
            f"{phase}: status={status}, copied={copied}/{total}, "
            f"remaining={remaining}, step={step_pages}, "
            f"progress={percent:.1f}%, elapsed={elapsed:.2f}s"
            f"{restart_note}"
        )
        self.previous_remaining = remaining

getattr(sqlite3, "SQLITE_DONE", 101) 让代码既能使用模块常量,也能在较旧运行环境中按 SQLite 的固定完成码回退。实际业务如果要推送 Prometheus、日志或 GUI,只需把 print 换成对应的指标更新逻辑。

total、remaining、copied、percent、previous remaining、step pages 与 status 之间计算关系的静态指标图
图2:remaining 是核心观测值;copied、percent 和 step_pages 都应从当前与上一次快照计算。

压测方法:用 pages 控制观察粒度

pages 表示每次迭代复制的页面数。它小于或等于 0 时,Python 会在单个步骤中复制整个数据库;这样回调仍可用,但通常只能看到很少的进度节点。需要更细的进度时,可以设置一个正整数,例如 128 或 256,再根据业务负载调整。

import sqlite3


source = sqlite3.connect("app.db")
target = sqlite3.connect("app-backup.db")
progress = BackupProgress()

try:
    # 每次最多复制 256 页,便于观察中间进度并缩短单次持锁区间。
    with target:
        source.backup(
            target,
            pages=256,
            progress=progress,
            sleep=0.05,
        )
finally:
    # 无论成功还是异常都关闭两个连接,避免文件描述符长期占用。
    target.close()
    source.close()

sleep 是备份剩余页面时连续尝试之间的等待秒数,不是每复制一批页面后固定暂停的性能节流器。官方说明还指出,在线备份可以在其他客户端或同一连接并发访问数据库时工作。

结果对比:应该看 remaining,还是看回调次数

观察方式能否判断剩余页数可靠性
直接记录 remaining可以最直接,来自最近一次备份迭代
total - remaining可以反推适合显示已完成页数和百分比
回调次数 × pages不能准确判断忽略最后一轮、锁竞争与重启
数据库文件字节数不能直接替代页数与文件布局、WAL 等因素不是同一指标
经过时间不能直接替代只能用于趋势,不能说明还剩多少页

如果要做吞吐量对比,应记录真实的 step_pages 与相邻回调的时间差,再计算 pages/s。不要给 remaining 随意乘一个固定值就宣称是精确剩余字节,也不要在只有一两个样本时给出稳定 ETA。

边界条件:为什么 remaining 可能突然变大

SQLite 官方在线备份文档说明:如果另一线程或进程在备份暂停期间写入源数据库,SQLite 会检测变化,并且通常在下一次备份步骤时重启备份。因此,remaining 和 total 是最近一次 backup_step 保存的快照,不是每次读取时重新扫描源数据库得到的绝对实时值。

这会带来三个工程结论:

  • 进度条可以短暂回退,不要用 assert remaining 作为正确性检查。
  • 源库持续高频写入时,备份可能反复重启,完成时间会明显拉长。
  • 最终成功返回时,目标库仍是源库的一致、最新快照;中间进度值主要用于观测,而不是事务证明。

常见问题

remaining 为 0 就一定备份成功了吗?

它表示没有待复制页面。记录器同时检查 status == sqlite3.SQLITE_DONE,可以更明确地识别完成迭代;整个 backup() 正常返回才是调用层面的成功结果,异常仍应由外围错误处理捕获。

pages=256 是否代表每次回调一定复制 256 页?

不一定。它是单次迭代的页面数量设置,最后一轮可能不足 256 页,遇到忙或锁定状态时也可能没有产生预期增量。

能不能用 remaining 直接计算剩余秒数?

不能直接计算。需要用多次回调得到近期 pages/s,再做近似估算;一旦源库并发写入触发重启,旧速率和旧分母都可能失真。

total 为 0 时百分比怎么处理?

空数据库或特殊初始状态下要避免除零。示例把 total == 0 视为 100%,同时仍以 status 和 remaining 判断阶段。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
用 weak.Pointer 构建可自动失效的元数据缓存用 weak.Pointer 构建可自动失效的元数据缓存
上一篇
用 weak.Pointer 构建可自动失效的元数据缓存
Linux io_uring 固定缓冲区适合什么 IO 场景
下一篇
Linux io_uring 固定缓冲区适合什么 IO 场景
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    386次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    468次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    475次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    415次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    241次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码