SQLite以单文件数据库著称,这既是它最大的优点,也带来了一个隐患:所有数据集中在一个db文件里,一旦文件损坏或被误删,损失就是全部。比起MySQL、SQL Server这类有成熟备份体系的服务型数据库,SQLite的备份往往需要使用者自己动手搭建。好消息是,在Windows系统上,借助系统自带的工具就能实现完全自动化的定时备份,不需要购买任何商业软件。本文将从备份原理讲起,逐步给出一套可直接使用的bat脚本和PowerShell脚本方案。

为什么不能直接复制db文件
很多人备份SQLite的第一反应就是复制粘贴db文件,比如把C:\Data\app.db直接拷贝到别的地方。这种方式在数据库完全关闭的状态下没有问题,但如果应用程序正在运行、数据库处于写入过程中,直接复制得到的文件很可能是损坏的或不完整的。SQLite在写入时依赖WAL日志和共享内存文件,简单复制主文件而忽略这些附属文件,备份出来的数据在恢复时极有可能报database disk image is malformed错误。
正确的做法是使用SQLite官方提供的在线备份机制。通过sqlite3命令行工具的.backup命令,数据库会在一个事务内完成快照读取,即使源数据库正在被并发写入,得到的备份文件也保证是一致的。另一个选择是VACUUM INTO语句,它是SQLite 3.27之后引入的语法,效果类似且能顺带压缩碎片,但要求目标文件事先不存在,用起来稍有不便。综合来看,日常备份脚本推荐使用.backup命令。
准备工作很简单:从SQLite官网下载sqlite-tools的Windows版本,解压后会得到sqlite3.exe,建议将其放到一个固定目录,例如C:\Tools\sqlite3\,并把这个目录加入系统PATH环境变量,这样脚本在任何位置都能直接调用。
bat批处理版备份脚本
批处理脚本胜在简单直接,兼容所有Windows版本。下面的脚本实现了备份、时间戳命名、以及保留最近N份历史备份的功能:
@echo off
setlocal enabledelayedexpansion
rem 源数据库与备份目录配置
set "SRC_DB=C:\Data\app.db"
set "BACKUP_DIR=D:\Backup\sqlite"
set "KEEP_DAYS=7"
set "SQLITE3=C:\Tools\sqlite3\sqlite3.exe"
rem 创建备份目录(不存在时自动建立)
if not exist "%BACKUP_DIR%" mkdir "%BACKUP_DIR%"
rem 生成形如 20240115_143025 的时间戳
for /f "tokens=1-3 delims=/- " %%a in ("%date% %time: =0%") do (
set "d=%%a%%b%%c"
)
set "d=%d:~0,8%"
set "t=%time:~0,8%"
set "t=%t::=%"
set "t=%t:.=%"
set "STAMP=%d%_%t%"
rem 执行在线备份
"%SQLITE3%" "%SRC_DB%" ".backup '%BACKUP_DIR%\app_%STAMP%.db'"
if errorlevel 1 (
echo 备份失败,请检查数据库路径和sqlite3.exe位置
exit /b 1
)
rem 删除超过保留天数的旧备份
forfiles /p "%BACKUP_DIR%" /m "app_*.db" /d -%KEEP_DAYS% /c "cmd /c del @path" 2>nul
echo 备份完成:%BACKUP_DIR%\app_%STAMP%.db
endlocal
脚本中有几个细节值得注意。第一,.backup命令的目标路径要用单引号包起来,这是sqlite3 shell的语法要求;第二,删除旧备份用的是系统自带的forfiles命令,参数/d -7表示修改时间在7天之前的文件,避免备份目录无限膨胀;第三,errorlevel判断可以及时发现备份失败,方便后续接入报警。
建议把脚本保存为C:\Scripts\sqlite_backup.bat。如果数据库名不固定,可以把SRC_DB改成通过参数传入:%1,调用时写成sqlite_backup.bat C:\Data\app.db即可,这样一个脚本能服务多个数据库。
PowerShell进阶版:带日志与完整性校验
bat脚本够用但不够优雅,比如时间戳处理繁琐、没有日志、无法校验备份文件是否完好。PowerShell在这些方面都强得多,而且同样是Windows自带,无需额外安装。下面的脚本增加了备份日志、PRAGMA integrity_check完整性校验和失败自动清理:
# sqlite_backup.ps1
$SrcDb = "C:\Data\app.db"
$BackupDir = "D:\Backup\sqlite"
$KeepCount = 30
$Sqlite3 = "C:\Tools\sqlite3\sqlite3.exe"
$LogFile = "D:\Backup\sqlite\backup.log"
if (-not (Test-Path $BackupDir)) {
New-Item -ItemType Directory -Path $BackupDir | Out-Null
}
$stamp = Get-Date -Format "yyyyMMdd_HHmmss"
$target = Join-Path $BackupDir ("app_{0}.db" -f $stamp)
# 执行在线备份
& $Sqlite3 $SrcDb ".backup '$target'"
if ($LASTEXITCODE -ne 0 -or -not (Test-Path $target)) {
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') 备份失败" | Out-File $LogFile -Append
exit 1
}
# 校验备份文件完整性
$check = & $Sqlite3 $target "PRAGMA integrity_check;"
if ($check -ne "ok") {
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') 校验失败,已删除可疑备份" | Out-File $LogFile -Append
Remove-Item $target
exit 1
}
# 只保留最近 $KeepCount 份备份
Get-ChildItem $BackupDir -Filter "app_*.db" |
Sort-Object LastWriteTime -Descending |
Select-Object -Skip $KeepCount |
Remove-Item -Force
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') 备份成功:$target" | Out-File $LogFile -Append
这个版本的亮点在于备份后立即用PRAGMA integrity_check验证备份文件,只有返回ok才认为备份有效,否则直接删除可疑文件并记录日志。这种做法能避免一种糟糕的情况:备份一直正常运行,出事后恢复时才发现备份文件全是坏的。历史备份的清理也改成了按数量保留,比按天数保留更适合每天多次备份的场景。
需要注意,Power脚本默认受执行策略限制,用任务计划程序调用时要加上-ExecutionPolicy Bypass参数,或者直接用powershell.exe -File C:\Scripts\sqlite_backup.ps1 -ExecutionPolicy Bypass的形式启动,否则脚本可能被系统拒绝执行。
用任务计划程序实现定时自动执行
脚本写好之后,剩下的事交给Windows自带的任务计划程序。打开控制面板\管理工具\任务计划程序,点击右侧的创建基本任务,按向导设置即可。关键配置有四处:触发器建议选每天凌晨两点左右,避开业务高峰;操作选择启动程序;程序填写powershell.exe;参数填写-ExecutionPolicy Bypass -File C:\Scripts\sqlite_backup.ps1。
也可以用命令行一条搞定,方便在多台机器上批量部署:
schtasks /create /tn "SQLiteBackup" /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\sqlite_backup.ps1" /sc daily /st 02:00 /ru SYSTEM
用/ru SYSTEM以系统账户运行可以避免锁屏或用户未登录时任务不执行的问题。创建完成后,强烈建议手动右键任务选择运行一次,去备份目录确认文件确实生成了,再到事件查看器里看看有没有报错。很多人配置完定时任务就不管了,结果脚本路径写错导致几个月都没备份成功,这种教训并不少见。
最后提醒两点:一是备份目录尽量不要和数据库放在同一块物理磁盘上,否则磁盘一坏备份和原库一起没了,有条件的话把D:\Backup\sqlite同步到网络共享或云盘;二是定期做一次真实的恢复演练,拿备份文件换回原库跑一跑,确认数据完整可用。备份的意义不在于生成文件,而在于需要的那一刻能成功恢复。
SQLite备份Windows批处理数据库自动化修改时间:2026-09-06 19:48:39