- Fix markdown lint issues (MD030, MD047, MD051, MD028, MD005) - Update AI agents, architecture, implementation docs - Add new identity, face recognition, and API documentation - Remove deprecated face/person API guides
6.1 KiB
6.1 KiB
UUID 长度问题分析报告
Date: 2026-04-28 20:15 Issue: 16-char vs 32-char UUID formats
问题发现
实际数据统计
SELECT DISTINCT LENGTH(uuid) as len, COUNT(*) FROM dev.videos GROUP BY LENGTH(uuid);
-- Result:
len | count
-----+-------
16 | 20 -- 旧格式 (SHA256[0:16])
32 | 7479 -- 新格式 (SHA256[0:32])
384b0ff44aaaa1f14cb2cd63b3fea966 状态
| 字段 | 值 |
|---|---|
| uuid | 384b0ff44aaaa1f14cb2cd63b3fea966 (16 字符) |
| birth_registration | NULL |
| file_name | Old_Time_Movie_Show_-_Charade_1963.HD.mov |
UUID 格式对比
| 格式 | 长度 | 生成函数 | 用途 |
|---|---|---|---|
| 旧格式 | 16 | compute_uuid() |
早期视频注册 |
| 新格式 | 32 | compute_birth_uuid() |
Birth UUID (隐私保护) |
生成逻辑
旧格式 (16 字符):
// src/core/storage/uuid.rs:6-11
pub fn compute_uuid(user_path: &str, filename: &str) -> String {
let key = format!("{}/{}", user_path, filename);
let hash = Sha256::digest(key.as_bytes());
hex::encode(hash)[0..16].to_string() // 只取前 16 字符
}
新格式 (32 字符):
// src/core/storage/uuid.rs:82-91
pub fn compute_birth_uuid(
mac_address: &str,
timestamp: &str,
username: &str,
filename: &str,
) -> String {
let key = format!("{}|{}|{}|{}", mac_address, timestamp, username, filename);
let hash = Sha256::digest(key.as_bytes());
hex::encode(hash)[0..32].to_string() // 取前 32 字符
}
差异分析
隐私保护
| 特性 | 旧格式 | 新格式 |
|---|---|---|
| 包含元素 | Path + Filename | MAC + Time + User + Filename |
| 隐私风险 | 路径暴露 | 全部哈希化 |
| 唯一性 | 相对路径依赖 | MAC + Time 确保唯一 |
| 不可变性 | 迁移会改变 | 记录原始注册信息 |
代码判断逻辑
// src/core/storage/uuid.rs:94-96
pub fn is_birth_uuid(uuid: &str) -> bool {
uuid.len() == 32 && !uuid.contains('_')
}
数据库列定义
| 表 | 列 | 类型 | 可容纳 |
|---|---|---|---|
| videos | uuid | VARCHAR(32) | ✅ 16 + 32 |
| face_detections | file_uuid | VARCHAR(255) | ✅ 16 + 32 |
| chunks | uuid | VARCHAR(32) | ✅ 16 + 32 |
| jobs | asset_uuid | VARCHAR(32) | ✅ 16 + 32 |
影响范围
受影响的表
-- 查询使用 16 字符 UUID 的表
SELECT 'face_detections' as table_name, COUNT(*)
FROM dev.face_detections WHERE LENGTH(file_uuid) = 16;
SELECT 'chunks' as table_name, COUNT(*)
FROM dev.chunks WHERE LENGTH(uuid) = 16;
SELECT 'jobs' as table_name, COUNT(*)
FROM dev.jobs WHERE LENGTH(asset_uuid) = 16;
依赖关系
videos.uuid (16-char)
↓
face_detections.file_uuid (16-char) -- FK
chunks.uuid (16-char)
jobs.asset_uuid (16-char) -- FK
解决方案
方案 A: 保留兼容模式(推荐)
优点:
- 不破坏现有数据
- 无需大量迁移
- VARCHAR(32) 可容纳两种格式
缺点:
- 代码需要处理两种格式
is_birth_uuid()返回 false (16-char)- 部分功能受限(如 Birth UUID 查询)
实施:
- 保持现有数据不变
- 新视频使用 32 字符格式
- 代码兼容两种格式
方案 B: 强制迁移(破坏性)
优点:
- 统一格式
- 全部启用 Birth UUID 功能
- 代码简化
缺点:
- 破坏性更改
- 需要更新所有关联表
- 外键关系需重建
实施步骤:
-- 1. 生成新 UUID
UPDATE dev.videos
SET uuid = (
SELECT compute_birth_uuid(...)
)
WHERE LENGTH(uuid) = 16;
-- 2. 更新关联表
UPDATE dev.face_detections
SET file_uuid = (
SELECT new_uuid FROM videos WHERE old_uuid = file_uuid
)
WHERE LENGTH(file_uuid) = 16;
-- 3. 更新 chunks
UPDATE dev.chunks
SET uuid = (
SELECT new_uuid FROM videos WHERE old_uuid = uuid
)
WHERE LENGTH(uuid) = 16;
建议
当前阶段:兼容模式
理由:
-
384b0ff44aaaa1f14cb2cd63b3fea966 已有大量关联数据:
- face_detections: 78 条
- chunks: 5683 条
- jobs: 2 条
-
迁移风险高:
- 外键关系复杂
- 可能破坏现有功能
-
VARCHAR(32) 已足够:
- 可容纳两种格式
- 无需修改列定义
长期规划:渐进迁移
- Phase 1: 保持兼容
- Phase 2: 新注册使用 32 字符
- Phase 3: 逐步迁移旧数据(可选)
判断函数使用
// 检查是否是 Birth UUID
if is_birth_uuid(&uuid) {
// 启用 Birth UUID 相关功能
} else {
// 使用旧格式逻辑
}
受影响的功能
| 功能 | 依赖 | 影响 |
|---|---|---|
| Birth UUID 查询 | is_birth_uuid() |
16-char 无法查询 |
| 跨设备同步 | Birth UUID | 16-char 不支持 |
| 隐私保护 | Birth UUID | 16-char 不受保护 |
代码检查清单
需要兼容的代码
| 文件 | 行 | 需检查 |
|---|---|---|
uuid.rs:95 |
is_birth_uuid() | ✅ 已检查 |
uuid.rs:263 |
测试用例 | ✅ 已验证 |
postgres_db.rs:620 |
videos 表 | ✅ VARCHAR(32) |
rule1_ingest.rs:9 |
execute_rule1() | ✅ 使用 file_uuid 参数 |
face_recognition.rs |
face_detections | ✅ VARCHAR(255) |
无需修改的代码
- 所有参数类型使用
&str或String - VARCHAR 定义已足够
- 外键关系正常
结论
问题根源
384b0ff44aaaa1f14cb2cd63b3fea966 使用旧格式 UUID (16 字符),原因是:
- 早期注册(未启用 Birth UUID)
compute_uuid()只取 SHA256 前 16 字符- birth_registration = NULL
当前状态
- videos 表: VARCHAR(32) ✅ 可容纳两种格式
- 代码逻辑:
is_birth_uuid()区分两种格式 ✅ - 外键关系: 正常 ✅
建议
当前: 保持兼容模式,不强制迁移 未来: 新视频使用 32 字符 Birth UUID
相关文件
| 文件 | 说明 |
|---|---|
src/core/storage/uuid.rs |
UUID 生成逻辑 |
migrations/019_add_birth_registration.sql |
Birth UUID 表结构 |
migrations/025_rename_video_uuid_to_file_uuid.sql |
列重命名迁移 |