Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions docs/v1.1.0-upgrade-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# v1.1.0 SQL 升级操作指南

本文说明如何把数据库 schema 从 v1.0.x(与上游同步前)升级到 v1.1.0。命令示例一律使用占位符,本文不含任何真实凭据。

## 1. 适用范围

- 代码版本:从 v1.0.x(与上游同步前)升级到包含 v1.1.0 SQL 升级脚本的代码版本
- 数据库:PostgreSQL(schema 基线见 `resources/database/schema_pg.sql` 与 `init_data_pg.sql`)
- 升级脚本:`resources/database/upgrades/v1.1.0/` 下 9 个文件,按文件名日期序执行
- 本项目没有 Flyway / Liquibase 版本表,SQL 需手动执行

## 2. 前置检查

### 2.1 确认数据库是 PostgreSQL 且应用指向它

连接数据库执行 `SELECT version();`,应返回 PostgreSQL 版本。

再确认 `bootstrap/src/main/resources/application.yaml` 的 `spring.datasource`:

- `driver-class-name` 为 `org.postgresql.Driver`
- `url` 形如 `jdbc:postgresql://<host>:5432/<database>`(本项目默认库名 `ragent`)

### 2.2 确认当前 schema 版本

任选一种方法,判断是否已执行过部分升级脚本:

```sql
-- 已执行 260328:t_knowledge_document_chunk_log 应有 embed_duration / persist_duration 列
SELECT column_name
FROM information_schema.columns
WHERE table_name = 't_knowledge_document_chunk_log'
AND column_name IN ('embed_duration', 'persist_duration');
```

```sql
-- 已执行 260803:t_agent_profile 表应存在
SELECT to_regclass('public.t_agent_profile');
```

psql 交互式下也可用 `\d t_knowledge_document_chunk_log` 直接查看列清单。查询有结果说明对应脚本已执行过,可从下一个脚本开始或整体核对后跳过。

## 3. 备份(必须最先做)

### 3.1 全量备份

使用 pg_dump 自定义格式,文件名带日期时间:

```bash
pg_dump -h <host> -p 5432 -U <db-user> -Fc -f ragent_backup_20260811_153000.dump <database>
```

`-Fc` 表示自定义格式:压缩存储,且支持 pg_restore 选择性恢复。

### 3.2 校验备份

- `pg_restore --list ragent_backup_20260811_153000.dump` 能列出对象清单
- 抽查文件大小与库规模是否相符
- 备份前记录关键表行数(如 `t_message`、`t_knowledge_chunk`),升级后对比确认数据未丢失

### 3.3 恢复命令

恢复到新库(推荐演练方式):

```bash
createdb -h <host> -U <db-user> <database>_restore
pg_restore -h <host> -U <db-user> -d <database>_restore ragent_backup_20260811_153000.dump
```

覆盖现有库(谨慎,会先删除已存在对象):

```bash
pg_restore -h <host> -U <db-user> -d <database> -c --if-exists ragent_backup_20260811_153000.dump
```

若备份用的是纯文本格式(pg_dump 不带 `-Fc`),用 psql 恢复:

```bash
psql -h <host> -U <db-user> -d <database> -f ragent_backup_20260811_153000.sql
```

## 4. 执行升级脚本

### 4.1 执行顺序

严格按文件名日期序,逐个执行:

```text
1. 260328_knowledge_chunk_log_duration.sql
2. 260408_message_thinking.sql
3. 260703_knowledge_vector_collection.sql
4. 260709_biz_change_log.sql
5. 260722_01_message_sources.sql
6. 260722_02_message_recommendation_context.sql
7. 260725_intent_multi_collections.sql
8. 260730_ingestion_kernel.sql
9. 260803_agent_profile.sql
```

单文件执行命令:

```bash
psql -h <host> -U <db-user> -d <database> -v ON_ERROR_STOP=1 \
-f resources/database/upgrades/v1.1.0/260328_knowledge_chunk_log_duration.sql
```

`-v ON_ERROR_STOP=1` 让 psql 遇到第一条错误即停止,便于定位。PowerShell 下逐文件执行时同样加上该参数,不要用裸管道把 9 个文件拼成一条命令,否则无法定位失败点。

### 4.2 幂等性与重复执行

脚本大量使用 `CREATE TABLE IF NOT EXISTS`、`ADD COLUMN IF NOT EXISTS`、`DROP COLUMN IF EXISTS`、`CREATE INDEX IF NOT EXISTS`、`ON CONFLICT DO NOTHING`,重复执行安全,可放心重跑。

少数语句没有 IF 保护,重复执行会报错,但报的是"对象已存在/列不存在",不会破坏数据:

- 260328 的 `RENAME COLUMN`(第二次执行报列不存在)
- 260408 的 `ADD COLUMN`(第二次执行报列已存在)
- 260703 的 `ADD COLUMN` 与 `CREATE INDEX`(第二次执行报对象已存在)

遇到这类报错,按第 2.2 节的方法核对对象已存在即可继续,无需处理。

### 4.3 失败处理与回滚

- 脚本没有包裹显式事务,单条语句原子提交,失败的语句本身不会生效
- 执行中断后,先对照已创建对象(`\dt`、`\d`、`information_schema`),对已存在的跳过,再重跑失败的脚本
- 需要整体回滚时从第 3 节备份恢复:恢复到新库后切换连接,或 `-c --if-exists` 覆盖原库

## 5. 升级后验证清单

按脚本逐一抽查(统一查询示例见文末):

| 脚本 | 关键对象 | 验证点 |
|:---|:---|:---|
| 260328 | `t_knowledge_document_chunk_log` | 存在 `embed_duration`、`persist_duration` 列 |
| 260408 | `t_message` | 存在 `thinking_content`、`thinking_duration` 列 |
| 260703 | `t_knowledge_vector` | 存在 `collection_name` 列与索引 `idx_kv_collection_name` |
| 260709 | `t_biz_change_log` | 表存在,索引 `idx_biz_change_log_biz` / `_time` / `_operator` 存在 |
| 260722_01 | `t_message` | 存在 `sources`(JSONB)列 |
| 260722_02 | `t_message` | 存在 `recommended_questions`、`retrieved_chunks`、`reply_to_message_id`、`message_status` 列 |
| 260725 | `t_intent_node` | 存在 `collection_names`(JSONB)列,存量 `collection_name` 已迁移为单元素数组 |
| 260730 | `t_knowledge_document` 等 | 存在 `mime_type`、`ingestion_spec`;`chunk_strategy`、`chunk_config` 已删除;`t_knowledge_chunk.embedding_text` 存在;`t_knowledge_document_chunk_log.parse_profile` 存在 |
| 260803 | `t_agent_profile`、`t_agent_prompt` | 两表存在;`SELECT count(*) FROM t_agent_profile WHERE builtin = 1;` 返回 1 |

批量检查示例:

```sql
SELECT column_name
FROM information_schema.columns
WHERE table_name = 't_message'
AND column_name IN ('sources', 'thinking_content', 'recommended_questions', 'message_status')
ORDER BY column_name;
```

应用侧验证:

- 启动日志无缺列、缺表报错
- 控制台「智能体」菜单可用,默认助手(内置智能体)可见

## 6. 常见问题

权限不足

- 升级脚本含 DDL(建表、加列、建索引、加注释),需要相应权限:`CREATE TABLE` 需要目标 schema 的 `CREATE` 权限;`ALTER TABLE`、`CREATE INDEX`、`COMMENT ON` 需要对象 owner 或 SUPERUSER
- 最小权限建议:用数据库 owner 账号执行升级脚本;应用账号只保留 DML 权限。若执行账号不是相关表 owner 且报权限错误,改用 SUPERUSER,或先把相关表 owner 转移给执行账号

事务与中断

- 单条语句原子,中断不会留下半成品语句;按 4.3 节核对对象后重跑即可
- 不要跳过任何文件,日期序即依赖序

字符集

- 确认库为 UTF8 编码(PG 默认)
- 客户端连接带 `client_encoding=UTF8`(连接串参数或环境变量 `PGCLIENTENCODING=UTF8`)
- 260803 内置智能体提示词为中文,连接编码不对会乱码或写入失败

## 7. 本地开发库同样需要执行

本地开发库不执行这批脚本,新功能会直接不可用或报错:

- 智能体菜单(`t_agent_profile` / `t_agent_prompt`)
- 回答来源面板(`t_message.sources`)
- 推荐追问与消息状态(`t_message.recommended_questions` 等)
- 意图多 Collection(`t_intent_node.collection_names`)
- 摄取内核化(`t_knowledge_document.ingestion_spec` 等)

本地执行第 4 节的 psql 命令即可,执行前同样先备份。
Loading