4500335da7
此前每次启动裸跑 AutoMigrate + 一串手写索引/回填,且启动路径上有两处 DROP TABLE CASCADE 的 legacy 迁移;多实例并发启动无锁 → 并发 ALTER/建索引竞争,一方报错即掉降级。 务实硬化(不引外部工具,保留 gorm 结构体为源): - PG advisory lock:整段迁移在 pg_advisory_lock 内串行,多实例同时启动只有一个进锁跑, 其余阻塞等待。取锁 60s 超时兜底(取不到带告警继续,AutoMigrate/索引多幂等)。 - 破坏性 legacy 迁移移出默认路径:migrateLegacyIntIDs/migrateDocLinkToID(DROP TABLE CASCADE)默认不跑,仅 ALLOW_LEGACY_SCHEMA_MIGRATION=1 时执行;检测到旧 schema 但未开 只告警不动手。现网早已是雪花 id 本就不触发,但从此不再是启动就可能 DROP。 - 版本化 runner:AutoMigrate 之外的步骤(3 个部分唯一索引 + NULL 余额回填)登记为 schemaSteps,各跑一次并记入 sundynix_schema_migration 表,下次跳过;某步失败即停、 不记录、下次重试。将来 AutoMigrate 做不了的破坏性/数据迁移在末尾追加新 id 即可。 pgsql.go 的迁移块收敛为一句 runMigrations(db)。带 runner 单测(跑一次/跳过/追加/失败即停)。 现网 DB 已有的索引/回填重跑无害(IF NOT EXISTS / WHERE IS NULL),跑后记录。build+vet+test 绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>