ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

TaxHacker 数据迁移实战:v0.3 升级 v0.5 的 SQLite → PostgreSQL 完整指南

TaxHacker 数据迁移实战:v0.3 升级 v0.5 的 SQLite → PostgreSQL 完整指南 TaxHacker 数据迁移实战v0.3 升级 v0.5 的 SQLite → PostgreSQL 完整指南【免费下载链接】TaxHackerSelf-hosted AI accounting app. LLM analyzer for receipts, invoices, transactions with custom prompts and categories项目地址: https://gitcode.com/GitHub_Trending/ta/TaxHackerTaxHacker 在 v0.5 版本中完成了底层数据库从 SQLite 到 PostgreSQL 的切换由于两种数据库无法无缝在线迁移旧实例的数据需要借助应用内置的备份/恢复功能手动搬运。本文将围绕迁移文档docs/migrate-0.3-0.5.md给出的四步流程结合当前仓库源码讲解完整的迁移操作、备份 ZIP 归档的内部结构与恢复机制的底层实现并给出大文件上传失败的排查方法。读完本文你可以安全地在自己的自托管实例上完成 v0.3 → v0.5 的数据迁移且不丢失任何交易记录、附件和配置。迁移背景为什么 v0.5 不能无缝升级v0.5 将数据库从 SQLite 切换到了 PostgreSQL。从仓库的部署配置可以确认这一点docker-compose.yml 中已经内置了独立的postgres服务postgres:17-alpine应用通过DATABASE_URLpostgresql://postgres:postgrespostgres:5432/taxhacker连接数据库README 的环境变量表也将DATABASE_URL定义为 PostgreSQL 连接串PostgreSQL 17 推荐。数据库引擎的更换意味着旧版本 SQLite 文件中积累的数据无法被新版本直接读取因此官方文档明确说明迁移需要手动完成。但有一个关键保证——即使你已经提前升级到了 v0.5旧数据也没有丢失它仍然安全地保存在旧实例的数据目录中只要按正确顺序操作就能完整找回。从源码结构看Prisma 的迁移历史prisma/migrations从20250403104933_init起步随后依次叠加了 storage、token limit、stripe、business details、app data、progress、cached parse result、split tx items 等迁移最终演进到当前以 PostgreSQL 为底座的 schema这从侧面印证了 v0.3 到 v0.5 之间数据库结构经历了重大变化。整个迁移思路可以概括为四步回滚到 v0.3.0 → 在旧版本上导出备份 → 升级到 latest → 在新版本上恢复备份。Step 1把 docker-compose 锁定回 v0.3.0迁移的第一步是把应用镜像固定回 v0.3.0。之所以必须先回滚是因为备份归档需要由旧版本自己的备份导出逻辑生成才能保证与 v0.5 的恢复器兼容。修改 docker-compose 中app服务的镜像标签services: app: image: ghcr.io/vas3k/taxhacker:v0.3.0 ports: - 7331:7331 // 其余配置保持不变注意7331:7331是应用默认端口映射容器内外均使用 7331 端口对应 README 中PORT环境变量默认值。除镜像标签外其余所有配置卷挂载、环境变量、服务依赖都不要改动避免引入额外变量。Step 2重启应用并导出备份归档固定镜像版本后重启应用使 v0.3.0 生效docker compose down docker compose up -d重启完成后打开浏览器访问http://localhost:7331进入Settings → Backups页面点击Download Data Archive按钮把生成的.zip归档文件保存到本地机器。从源码看这个按钮对应备份设置页面的下载逻辑app/(app)/settings/backups/page.tsx/settings/backups/page.tsx)点击后会先启动一个 backup 类型的进度任务然后请求GET /settings/backups/data?progressId...下载taxhacker-backup.zip。下载期间界面会显示 Archiving x/y files 的实时进度。备份归档内部结构备份导出路由的实现位于 app/(app)/settings/backups/data/route.ts/settings/backups/data/route.ts)它使用JSZip在内存中构建归档内部结构如下taxhacker-backup.zip ├── data/ │ ├── metadata.json # 备份元信息版本号、时间戳、包含的模型文件清单 │ ├── settings.json # 用户设置含 LLM 提示词等 │ ├── currencies.json # 自定义货币 │ ├── categories.json # 分类 │ ├── projects.json # 项目 │ ├── fields.json # 自定义字段 │ ├── files.json # 文件元数据索引 │ ├── transactions.json # 全部交易记录 │ └── uploads/ # 上传的原始附件收据、发票、PDF 等几个值得注意的实现细节版本化元数据归档根目录固定写入metadata.json其中version字段当前为1.0同时记录生成时间戳和模型清单。恢复端正是靠这个字段做兼容性校验。模型数据以 JSON 导出每个数据表对应一个 JSON 文件导出逻辑由 models/backups.ts 中的MODEL_BACKUP数组驱动其顺序settings → currencies → categories → projects → fields → files → transactions在恢复时同样重要。单文件 64MB 上限导出时单个附件超过 64MB 会被跳过并打印警告Skipping large file ... 64MB limit避免把超大文件压入归档导致内存问题。进度上报每处理 2 秒或全部完成时向进度服务上报current/total这就是页面上进度文案的数据来源。Step 3升级 TaxHacker 到最新版本备份归档安全落地后把镜像标签改回最新版services: app: image: ghcr.io/vas3k/taxhacker:latest ports: - 7331:7331 // 其余配置保持不变再次重启让新版本v0.5PostgreSQL 底座生效docker compose down docker compose up -d此时新的实例使用全新的 PostgreSQL 数据库是干净的状态等待恢复数据。Step 4在新实例上恢复数据进入Settings → Backups页面找到Restore from a backup区域选择之前保存的 ZIP 归档勾选 I understand that it will permanently delete all existing data 确认框点击Restore from backup。等待几秒钟数据量大时按钮会显示 Restoring from backup... (it can take a while)恢复成功后页面会展示详细的导入统计列出每个数据文件的恢复条数。恢复机制的源码级原理恢复流程的服务端实现位于 app/(app)/settings/backups/actions.ts/settings/backups/actions.ts) 的restoreBackupAction整个流程分四步1. 归档校验。使用JSZip.loadAsync解压若 ZIP 损坏直接报 Bad zip archive随后读取data/metadata.json校验版本仅支持SUPPORTED_BACKUP_VERSIONS [1.0]不匹配会提示 Incompatible backup version。另外上传文件超过MAX_BACKUP_SIZE 256MB会直接拒绝。2. 清空现有数据。cleanupUserTables按MODEL_BACKUP的逆序逐表deleteMany先删交易、文件等引用方再删分类、项目等被引用方以规避外键约束同时递归删除用户上传目录。3. 按序恢复各表。遍历MODEL_BACKUP读取对应 JSON 文件逐条调用modelFromJSONmodels/backups.ts写入数据库。恢复前preprocessRowData会做类型清洗空字符串转null、JSON 字符串反序列化、ISO 日期字符串转Date、数字字符串转数值id和*Code结尾的字段除外保留字符串语义。交易记录恢复时通过category: { connect: { userId_code: ... } }重新挂接分类与项目。4. 恢复上传附件。根据files.json中记录的路径从归档的data/uploads/目录提取对应二进制内容写回磁盘写入前用safePathJoin并校验目标路径必须位于用户上传目录之内若检测到路径穿越path traversal会记录错误并跳过兼顾安全。文件元数据中的路径也会被规范化为相对路径后更新入库。恢复成功后你能看到什么页面会以绿色卡片展示 Backup restored successfully 及导入统计例如settings.json: N itemstransactions.json: N itemsUploaded attachments: N items至此旧实例的交易记录、分类、项目、自定义字段、货币、设置以及所有附件都完整回到了新实例中。故障排查上传报文件太大怎么办如果恢复时遇到关于文件大小的错误原因出在 Next.js Server Actions 的请求体上限。迁移文档明确提示编辑项目根目录的 next.config.ts把experimental.serverActions.bodySizeLimit调大const nextConfig: NextConfig { images: { unoptimized: true }, serverExternalPackages: [prisma/adapter-pg], experimental: { serverActions: { bodySizeLimit: 256mb, // 恢复备份上传走 Server Action受此限制 }, }, }当前仓库的默认值是256mb。恢复备份的上传请求正是通过 Server ActionrestoreBackupAction提交的而服务端同时还有MAX_BACKUP_SIZE 256MB的硬校验所以当你的备份归档接近或超过 256MB 时需要同时调大bodySizeLimit才能顺利上传。修改后重新构建并重启应用即可。补充提示导出侧还有单文件 64MB 的限制data/route.ts/settings/backups/data/route.ts) 中的MAX_FILE_SIZE如果你的实例中有超大附件即使恢复成功超大文件也不会被包含进归档迁移前需单独留意这部分文件。附录备份归档数据文件速查归档内文件内容对应数据模型metadata.json版本1.0、时间戳、模型清单—settings.json用户设置与 LLM 提示词Settingcurrencies.json货币列表Currencycategories.json分类及分类级 LLM 提示词Categoryprojects.json项目及项目级 LLM 提示词Projectfields.json自定义字段及提取提示词Fieldfiles.json附件元数据索引Filetransactions.json全部交易含金额、币种、分类/项目代码、extra 字段Transactionuploads/原始附件二进制磁盘文件这套备份格式由 models/backups.ts 的MODEL_BACKUP统一定义导出与恢复双向映射是 TaxHacker 数据可移植性的基石——它不仅支撑本次 v0.3 → v0.5 的数据库迁移也意味着你随时可以把数据完整导出迁移到任何一台新的自托管服务器上。【免费下载链接】TaxHackerSelf-hosted AI accounting app. LLM analyzer for receipts, invoices, transactions with custom prompts and categories项目地址: https://gitcode.com/GitHub_Trending/ta/TaxHacker创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表