101 lines
4.9 KiB
Markdown
101 lines
4.9 KiB
Markdown
# API 对齐数据库迁移运行手册
|
||
|
||
## 适用迁移
|
||
|
||
- MessageService:`20260909000100_ApiAlignmentFixes`
|
||
- MessageService:`20260911000100_ConversationUniqueness`
|
||
- GroupService:`20260909000200_ApiAlignmentFixes`
|
||
- FileService:`20260909000300_AsyncUploadResult`
|
||
|
||
## 发布前检查
|
||
|
||
先完成三个库的可恢复备份,并在对应数据库执行:
|
||
|
||
```sql
|
||
-- MessageService:记录迁移将处理的活动会话重复项。
|
||
SELECT UserId, ChatType, TargetId, COUNT(*) AS duplicate_count
|
||
FROM conversations
|
||
WHERE IsDeleted = 0
|
||
GROUP BY UserId, ChatType, TargetId
|
||
HAVING COUNT(*) > 1;
|
||
|
||
-- GroupService:新增 Id 唯一索引前必须无重复。
|
||
SELECT Id, COUNT(*) AS duplicate_count
|
||
FROM group_join_requests
|
||
GROUP BY Id
|
||
HAVING COUNT(*) > 1;
|
||
|
||
-- FileService:收紧 longtext 前检查历史最大长度。
|
||
SELECT
|
||
MAX(CHAR_LENGTH(FileName)) AS max_file_name,
|
||
MAX(CHAR_LENGTH(ContentType)) AS max_content_type,
|
||
MAX(CHAR_LENGTH(checksum_algorithm)) AS max_checksum_algorithm,
|
||
MAX(CHAR_LENGTH(checksum_value)) AS max_checksum_value,
|
||
MAX(CHAR_LENGTH(storage_provider)) AS max_storage_provider,
|
||
MAX(CHAR_LENGTH(storage_bucket)) AS max_storage_bucket,
|
||
MAX(CHAR_LENGTH(storage_key)) AS max_storage_key,
|
||
MAX(CHAR_LENGTH(storage_region)) AS max_storage_region
|
||
FROM upload_files;
|
||
```
|
||
|
||
上面的长度必须分别不超过 `255/255/16/128/64/255/1024/128`。对 `upload_tasks` 执行同样检查。超长值应先人工确认和修正,不要依赖数据库静默截断。
|
||
|
||
## 执行迁移
|
||
|
||
在仓库根目录设置目标数据库连接字符串后执行。不要把真实密码写入仓库或命令记录。
|
||
|
||
```powershell
|
||
$env:DefaultDB_ConnStr = '<MessageService MySQL connection string>'
|
||
dotnet ef database update --project MessageService.Infrastructure --startup-project MessageService.WebApi --context MessageDbContext
|
||
|
||
$env:DefaultDB_ConnStr = '<GroupService MySQL connection string>'
|
||
dotnet ef database update --project GroupService.Infrastructure --startup-project GroupService.WebApi --context GroupDbContext
|
||
|
||
$env:DefaultDB_ConnStr = '<FileService MySQL connection string>'
|
||
dotnet ef database update --project FileService.Infrastructure --startup-project FileService.WebApi --context FileDbContext
|
||
```
|
||
|
||
建议顺序为 Message → Group → File,随后发布后端,再发布最终前端包。
|
||
|
||
本地具备 Docker 时执行 MessageService 的 MySQL 8 集成测试:
|
||
|
||
```powershell
|
||
$env:RUN_DOCKER_TESTS = '1'
|
||
dotnet test MessageService.Tests/MessageService.Tests.csproj
|
||
```
|
||
|
||
未设置该变量时,`dotnet test IM_API_NEW.sln` 仍会运行领域模型和迁移脚本检查,并明确跳过需要 Docker 的两项测试。
|
||
|
||
## 数据兼容说明
|
||
|
||
- 所有新业务列均可空或有安全默认值,不删除历史记录。
|
||
- 历史文件的 `IsPublic` 默认 `false`,无法确认作用域的旧文件因此只允许所有者读取。
|
||
- 新上传文件会写入 `SourceTaskId/ChatType/TargetId/ResultFileId`;不要批量猜测旧文件作用域。
|
||
- 群退出、群解散和会话隐藏使用软删除。
|
||
- 会话唯一性迁移不会物理删除记录;它保留更新时间最新的一条活动会话,将其他重复项软删除,并创建只约束活动记录的生成列唯一索引。
|
||
- Docker Compose 要求从环境注入 MySQL、RabbitMQ 和内部 API 凭据,可复制 `.env.example` 后填入部署环境的真实值;不得提交 `.env`。
|
||
|
||
## 回滚
|
||
|
||
只有在已经回滚依赖新字段/接口的前后端版本后,才允许回滚数据库迁移:
|
||
|
||
```powershell
|
||
$env:DefaultDB_ConnStr = '<MessageService MySQL connection string>'
|
||
dotnet ef database update 20260423115234_InitMessageDb --project MessageService.Infrastructure --startup-project MessageService.WebApi --context MessageDbContext
|
||
|
||
$env:DefaultDB_ConnStr = '<GroupService MySQL connection string>'
|
||
dotnet ef database update 20260429103435_removeGroupRequestOperatorProfile --project GroupService.Infrastructure --startup-project GroupService.WebApi --context GroupDbContext
|
||
|
||
$env:DefaultDB_ConnStr = '<FileService MySQL connection string>'
|
||
dotnet ef database update 20260509073447_InitFileDb --project FileService.Infrastructure --startup-project FileService.WebApi --context FileDbContext
|
||
```
|
||
|
||
FileService 回滚会删除新作用域和任务结果列,并把收紧的字符串列恢复为 `longtext`;回滚前应另行导出这些新列的数据。
|
||
# 20260913000100 会话活动时间与消息搜索
|
||
|
||
部署消息服务前先备份数据库,并在 MySQL 8 测试库执行 `20260913000100_ConversationActivityAndMessageSearch`。
|
||
|
||
- 迁移新增可空 `conversations.LastMessageTime`,按相同 `StreamKey` 的最新未删除消息时间回填;没有消息时回退到会话创建时间。
|
||
- 新增 `messages(StreamKey, MsgType, State, SequenceId)` 复合索引,为会话内文本搜索和独占游标分页提供支持。
|
||
- 迁移只更新内部存储结构,不改变现有 DTO;发布后确认旧会话排序未因已读操作变化,并抽查搜索翻页无重复。
|