parent_object_id was never written or read by any application code (verified via repo-wide grep: only the baseline migration and the ORM model referenced it). The orphan index idx_storage_parent likewise served nothing. Tree structure is maintained entirely via the materialized path in storage_objects.relative_path (LIKE-prefix queries in backend/src/backend/scripts.py: list_workspace_tree, list_workspace_directories). The column mislead a prior review into proposing an adjacency-list table — removing it eliminates that temptation for the next reader. Migration: migrations/versions/f7a8b9c0d1e2_drop_storage_parent.py - Drops idx_storage_parent first, then parent_object_id (correct order on MySQL). - MySQL 8.0 has no IF EXISTS on DROP INDEX / DROP COLUMN, so calls are unconditional. - Updates the storage_objects TABLE COMMENT so the materialized-path warning reaches the DB, not just the ORM (Codex review finding). - Downgrade restores both. Model: common/src/common/db/models/storage.py - Removes the dead Index entry and the dead column. - Refreshes the table comment to flag the materialized-path contract. Verified: - alembic upgrade head: applied, head = f7a8b9c0d1e2 - SHOW INDEX / SHOW COLUMNS: 0 rows - TABLE COMMENT updated in information_schema - pytest backend/tests: 43 passed
Migrations
MySQL 8 Alembic 迁移目录。
当前链路:
20260724_0001 完整业务 Schema 基线
20260728_0002 Demo 用户、角色、Workspace 数据
20260728_0003 调度稳定版本可见性字段
20260730_0004 编辑租约字段 redis_lock_key -> lock_key 兼容迁移
Docker Compose 中的 migrate 一次性容器会在 Backend 和 Runtime 启动前执行:
alembic upgrade head
本地执行:
export DATABASE_URL='mysql+asyncmy://user:password@127.0.0.1:3308/model_platform?charset=utf8mb4'
uv run --package backend alembic current
uv run --package backend alembic upgrade head
已发布的旧 revision 不应再修改;后续表结构调整必须新增 revision。