| # PostgreSQL 迁移实施文档 |
|
|
| ## 1. 问题描述 |
|
|
| 在将 AnythingLLM 从 SQLite 迁移到 PostgreSQL 过程中,用户遇到了以下错误: |
|
|
| ### 错误信息 |
| - **P3018 错误**: `A migration failed to apply. New migration failed to apply` |
| - **P3009 错误**: `migration found a failed migration` |
|
|
| ### 具体错误详情 |
| 执行 `npx prisma migrate dev` 时出现: |
| ``` |
| Error: P3018 |
| |
| A migration failed to apply. New migration failed to apply. |
| |
| Query failed: database error |
| ERROR: syntax error at or near "AUTOINCREMENT" |
| LINE 1: ...id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT |
| ``` |
|
|
| ## 2. 错误原因分析 |
|
|
| ### 2.1 根本原因 |
| Prisma 生成的迁移文件包含了 SQLite 特定的 `AUTOINCREMENT` 语法,但 PostgreSQL 不支持此语法。 |
|
|
| ### 2.2 问题详情 |
| - **SQLite 语法**: `PRIMARY KEY AUTOINCREMENT` |
| - **PostgreSQL 语法**: 使用 `SERIAL` 或 `BIGSERIAL` 类型,或使用 `IDENTITY` 列 |
|
|
| ### 2.3 受影响的表 |
| 查看迁移文件发现以下表都使用了 `AUTOINCREMENT`: |
| - `api_keys` |
| - `workspace_documents` |
| - `invites` |
| - `system_settings` |
| - `users` |
| - `document_vectors` |
| - `welcome_messages` |
| - `workspaces` |
| - `workspace_chats` |
| - `workspace_users` |
| - `workspace_parsed_files` |
|
|
| ## 3. 解决方案 |
|
|
| ### 方案一:重置迁移(推荐用于开发环境) |
|
|
| ```bash |
| # 1. 删除所有迁移文件 |
| rm -rf server/prisma/migrations/* |
| |
| # 2. 重置数据库 |
| npx prisma migrate reset --force |
| |
| # 3. 重新生成迁移 |
| npx prisma migrate dev --name init |
| ``` |
|
|
| ### 方案二:手动修复迁移文件 |
|
|
| ```bash |
| # 1. 编辑迁移文件,将 AUTOINCREMENT 替换为 PostgreSQL 语法 |
| # 例如: |
| # 原始:id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT |
| # 修改为:id SERIAL PRIMARY KEY |
| |
| # 2. 手动执行修复后的 SQL |
| psql $DATABASE_URL -f server/prisma/migrations/20230921191814_init/migration.sql |
| ``` |
|
|
| ### 方案三:使用 Prisma 数据迁移功能 |
|
|
| ```bash |
| # 1. 创建新的空迁移 |
| npx prisma migrate dev --name fix-postgresql-syntax --create-only |
| |
| # 2. 编辑新迁移文件,添加修复 SQL |
| ``` |
|
|
| ## 4. 具体实施步骤 |
|
|
| ### 4.1 环境准备 |
|
|
| ```bash |
| # 1. 安装 PostgreSQL |
| # Ubuntu/Debian |
| sudo apt-get install postgresql postgresql-contrib |
| |
| # 2. 创建数据库和用户 |
| sudo -u postgres psql |
| CREATE USER anythingllm WITH PASSWORD 'your_password'; |
| CREATE DATABASE anythingllm OWNER anythingllm; |
| GRANT ALL PRIVILEGES ON DATABASE anythingllm TO anythingllm; |
| \q |
| |
| # 3. 配置环境变量 |
| export DATABASE_URL="postgresql://anythingllm:your_password@localhost:5432/anythingllm" |
| ``` |
|
|
| ### 4.2 使用方案一的实施步骤 |
|
|
| ```bash |
| # 进入项目目录 |
| cd /path/to/anythingllm |
| |
| # 1. 备份现有数据(如果需要) |
| sqlite3 server/storage/anythingllm.db ".backup backup.db" |
| |
| # 2. 删除现有迁移 |
| rm -rf server/prisma/migrations/* |
| |
| # 3. 更新 schema.prisma 确保使用正确的数据库类型 |
| # 确保 provider = "postgresql" |
| |
| # 4. 重置并重新生成迁移 |
| npx prisma migrate reset --force |
| npx prisma migrate dev --name init |
| |
| # 5. 生成客户端 |
| npx prisma generate |
| |
| # 6. 运行种子数据(如果有) |
| node server/prisma/seed.js |
| ``` |
|
|
| ### 4.3 手动迁移数据(从 SQLite 到 PostgreSQL) |
|
|
| ```bash |
| # 1. 安装迁移工具 |
| npm install -g pgloader |
| |
| # 2. 创建迁移配置文件 load.command |
| LOAD DATABASE |
| FROM sqlite://server/storage/anythingllm.db |
| INTO postgresql://anythingllm:your_password@localhost:5432/anythingllm |
| |
| WITH include no drop, create tables, create indexes, reset sequences, foreign keys |
| |
| SET maintenance_work_mem to '128MB', work_mem to '12MB'; |
| |
| CAST |
| type datetime to timestamptz drop default drop not null using zero-datetime-to-timestamptz, |
| type date drop not null drop default using zero-date-to-date; |
| |
| # 3. 执行迁移 |
| pgloader load.command |
| ``` |
|
|
| ## 5. 预防措施 |
|
|
| ### 5.1 开发实践 |
|
|
| 1. **使用数据库抽象** |
| - 在 schema.prisma 中使用 Prisma 的类型系统 |
| - 避免使用特定数据库的原始 SQL |
|
|
| 2. **多数据库测试** |
| ```bash |
| # 在 CI/CD 中测试多个数据库 |
| # SQLite |
| DATABASE_URL="file:./dev.db" npx prisma migrate dev |
| |
| # PostgreSQL |
| DATABASE_URL="postgresql://user:pass@localhost/db" npx prisma migrate dev |
| ``` |
|
|
| 3. **迁移审查** |
| - 所有迁移文件需要代码审查 |
| - 检查是否使用了特定数据库语法 |
|
|
| ### 5.2 配置管理 |
|
|
| ```javascript |
| // prisma/schema.prisma |
| generator client { |
| provider = "prisma-client-js" |
| } |
| |
| datasource db { |
| provider = "postgresql" // 明确指定数据库类型 |
| url = env("DATABASE_URL") |
| } |
| ``` |
|
|
| ## 6. 最佳实践 |
|
|
| ### 6.1 多数据库支持建议 |
|
|
| 1. ** schema 设计原则** |
| - 使用 Prisma 的标准类型 |
| - 避免使用特定数据库的功能 |
| - 保持模型简单和可移植 |
|
|
| 2. **迁移策略** |
| ```bash |
| # 创建迁移时指定数据库 |
| npx prisma migrate dev --create-only --name add_new_feature |
| |
| # 检查生成的 SQL |
| cat server/prisma/migrations/*/migration.sql |
| |
| # 应用迁移 |
| npx prisma migrate dev |
| ``` |
|
|
| 3. **测试策略** |
| - 在开发中使用 SQLite |
| - 在测试和生产中使用 PostgreSQL |
| - 定期在不同数据库间测试迁移 |
|
|
| ### 6.2 生产环境部署 |
|
|
| ```yaml |
| # docker-compose.yml |
| version: '3.8' |
| services: |
| postgres: |
| image: postgres:15 |
| environment: |
| POSTGRES_DB: anythingllm |
| POSTGRES_USER: anythingllm |
| POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} |
| volumes: |
| - postgres_data:/var/lib/postgresql/data |
| ports: |
| - "5432:5432" |
| |
| anything-llm: |
| build: . |
| environment: |
| DATABASE_URL: "postgresql://anythingllm:${POSTGRES_PASSWORD}@postgres:5432/anythingllm" |
| depends_on: |
| - postgres |
| ports: |
| - "3001:3001" |
| |
| volumes: |
| postgres_data: |
| ``` |
|
|
| ### 6.3 监控和维护 |
|
|
| 1. **数据库监控** |
| ```sql |
| -- 检查表大小 |
| SELECT |
| schemaname, |
| tablename, |
| pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size |
| FROM pg_tables |
| WHERE schemaname = 'public' |
| ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC; |
| ``` |
|
|
| 2. **定期维护** |
| ```bash |
| # 更新统计信息 |
| npx prisma db execute --stdin <<< "ANALYZE;" |
| |
| # 清理旧数据(根据需要) |
| npx prisma db execute --stdin <<< "VACUUM;" |
| ``` |
|
|
| ## 7. 故障排除 |
|
|
| ### 7.1 常见错误及解决方案 |
|
|
| 1. **连接错误** |
| ``` |
| Error: P1001: Can't reach database server |
| ``` |
| 解决方案:检查 PostgreSQL 服务是否运行,验证连接字符串 |
|
|
| 2. **权限错误** |
| ``` |
| Error: P1003: Database does not exist |
| ``` |
| 解决方案:创建数据库并授予正确权限 |
|
|
| 3. **迁移冲突** |
| ``` |
| Error: P1010: Database error |
| ``` |
| 解决方案:使用 `prisma migrate resolve` 解决冲突 |
|
|
| ### 7.2 调试命令 |
|
|
| ```bash |
| # 检查迁移状态 |
| npx prisma migrate status |
| |
| # 查看数据库信息 |
| npx prisma db execute --stdin <<< "SELECT version();" |
| |
| # 测试连接 |
| npx prisma db push --preview-feature |
| ``` |
|
|
| ## 8. 总结 |
|
|
| PostgreSQL 迁移的主要挑战在于数据库语法差异。通过遵循本文档的解决方案和最佳实践,可以成功将 AnythingLLM 从 SQLite 迁移到 PostgreSQL,并获得更好的性能和可扩展性。 |
|
|
| 关键要点: |
| 1. 使用 Prisma 的抽象层避免特定数据库语法 |
| 2. 在开发早期测试多数据库兼容性 |
| 3. 建立完善的迁移和测试流程 |
| 4. 定期备份和维护数据库 |