191 lines
3.9 KiB
Markdown
191 lines
3.9 KiB
Markdown
# 数据库迁移系统
|
||
|
||
## 概述
|
||
|
||
本项目使用版本化的数据库迁移系统,支持增量更新和自动同步。
|
||
|
||
## 特性
|
||
|
||
- ✅ 版本管理:每个迁移有唯一版本号
|
||
- ✅ 增量执行:只执行未执行的迁移
|
||
- ✅ 自动运行:服务器启动时自动执行迁移
|
||
- ✅ 幂等性:重复执行不会出错
|
||
- ✅ 迁移记录:记录所有已执行的迁移
|
||
|
||
## 迁移文件命名规范
|
||
|
||
```
|
||
XXXX-description.js
|
||
```
|
||
|
||
- `XXXX`: 4位数字版本号(如 0001, 0002)
|
||
- `description`: 迁移描述(使用短横线分隔)
|
||
|
||
示例:
|
||
- `0001-add-danmaku-fields.js`
|
||
- `0002-add-user-avatar.js`
|
||
|
||
## 创建新迁移
|
||
|
||
### 1. 创建迁移文件
|
||
|
||
在 `backend/migrations/` 目录下创建新文件:
|
||
|
||
```javascript
|
||
/**
|
||
* 迁移: 添加用户头像字段
|
||
* 版本: 0002
|
||
* 日期: 2025-01-09
|
||
*/
|
||
|
||
module.exports = {
|
||
async up(manager) {
|
||
console.log(' - 添加 avatar 字段...');
|
||
await manager.executeSql(`
|
||
ALTER TABLE Users ADD COLUMN avatar TEXT;
|
||
`);
|
||
},
|
||
|
||
async down(manager) {
|
||
// 回滚逻辑(可选)
|
||
console.log(' - 回滚不支持');
|
||
}
|
||
};
|
||
```
|
||
|
||
### 2. 迁移方法
|
||
|
||
#### `up(manager)` - 升级
|
||
执行数据库变更的方法。
|
||
|
||
可用的 manager 方法:
|
||
- `executeSql(sql)`: 执行SQL语句
|
||
- `db`: 直接访问数据库连接
|
||
|
||
#### `down(manager)` - 回滚(可选)
|
||
回滚数据库变更的方法。
|
||
|
||
注意:SQLite 不支持 DROP COLUMN,回滚可能需要重建表。
|
||
|
||
## 执行迁移
|
||
|
||
### 自动执行(推荐)
|
||
|
||
服务器启动时会自动执行所有未执行的迁移:
|
||
|
||
```bash
|
||
# 开发环境
|
||
cd backend
|
||
npm start
|
||
|
||
# 生产环境(Docker)
|
||
docker-compose up -d
|
||
# 或
|
||
docker-compose restart
|
||
```
|
||
|
||
### 手动执行
|
||
|
||
#### 在容器内执行:
|
||
|
||
```bash
|
||
# Windows
|
||
migrate.bat
|
||
|
||
# Linux/Mac
|
||
chmod +x migrate.sh
|
||
./migrate.sh
|
||
```
|
||
|
||
#### 直接在容器中执行:
|
||
|
||
```bash
|
||
docker exec quanyoumi-app node /app/backend/migrations/index.js
|
||
```
|
||
|
||
## 迁移状态
|
||
|
||
迁移执行记录保存在 `migrations` 表中:
|
||
|
||
```sql
|
||
SELECT * FROM migrations;
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
id | version | name | executed_at
|
||
---+---------+-----------------------+---------------------
|
||
1 | 1 | add-danmaku-fields | 2025-01-09 10:30:00
|
||
2 | 2 | add-user-avatar | 2025-01-09 11:00:00
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
### Q: 迁移失败怎么办?
|
||
|
||
A: 检查错误日志,修复问题后重新启动服务器。已执行的迁移不会重复执行。
|
||
|
||
### Q: 如何回滚迁移?
|
||
|
||
A: 目前不支持自动回滚。如需回滚,请手动修改数据库或创建新的迁移来撤销更改。
|
||
|
||
### Q: 可以修改已执行的迁移吗?
|
||
|
||
A: 不建议。已执行的迁移不应修改。如需更改,请创建新的迁移。
|
||
|
||
### Q: 迁移在什么时候执行?
|
||
|
||
A: 服务器启动时自动执行。也可以手动运行 `migrate.bat` 或 `migrate.sh`。
|
||
|
||
## 最佳实践
|
||
|
||
1. **版本号递增**:新迁移的版本号应大于所有现有迁移
|
||
2. **描述清晰**:文件名和注释应清楚说明迁移目的
|
||
3. **测试迁移**:在开发环境测试后再部署到生产环境
|
||
4. **幂等性**:迁移应该可以安全地重复执行
|
||
5. **小步迭代**:每个迁移只做一件事,便于追踪和回滚
|
||
|
||
## 示例
|
||
|
||
### 添加新字段
|
||
|
||
```javascript
|
||
module.exports = {
|
||
async up(manager) {
|
||
await manager.executeSql(`
|
||
ALTER TABLE Activities ADD COLUMN featured INTEGER DEFAULT 0;
|
||
`);
|
||
}
|
||
};
|
||
```
|
||
|
||
### 创建新表
|
||
|
||
```javascript
|
||
module.exports = {
|
||
async up(manager) {
|
||
await manager.executeSql(`
|
||
CREATE TABLE IF NOT EXISTS Comments (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
activityId INTEGER NOT NULL,
|
||
userId INTEGER NOT NULL,
|
||
content TEXT NOT NULL,
|
||
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
`);
|
||
}
|
||
};
|
||
```
|
||
|
||
### 修改数据
|
||
|
||
```javascript
|
||
module.exports = {
|
||
async up(manager) {
|
||
await manager.executeSql(`
|
||
UPDATE Activities SET status = 'completed' WHERE endTime < datetime('now');
|
||
`);
|
||
}
|
||
};
|
||
```
|