File size: 7,320 Bytes
0fb4a2f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# 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. 定期备份和维护数据库 |