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. 定期备份和维护数据库