Files
momentry_core/docs_v1.0/UUID_LENGTH_ISSUE.md
Warren 4d75b2e251 docs: update docs_v1.0/ documentation
- 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
2026-04-30 15:10:41 +08:00

6.1 KiB
Raw Permalink Blame History

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 查询)

实施:

  1. 保持现有数据不变
  2. 新视频使用 32 字符格式
  3. 代码兼容两种格式

方案 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;

建议

当前阶段:兼容模式

理由:

  1. 384b0ff44aaaa1f14cb2cd63b3fea966 已有大量关联数据:

    • face_detections: 78 条
    • chunks: 5683 条
    • jobs: 2 条
  2. 迁移风险高:

    • 外键关系复杂
    • 可能破坏现有功能
  3. VARCHAR(32) 已足够:

    • 可容纳两种格式
    • 无需修改列定义

长期规划:渐进迁移

  1. Phase 1: 保持兼容
  2. Phase 2: 新注册使用 32 字符
  3. 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)

无需修改的代码

  • 所有参数类型使用 &strString
  • VARCHAR 定义已足够
  • 外键关系正常

结论

问题根源

384b0ff44aaaa1f14cb2cd63b3fea966 使用旧格式 UUID (16 字符),原因是:

  1. 早期注册(未启用 Birth UUID
  2. compute_uuid() 只取 SHA256 前 16 字符
  3. 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 列重命名迁移