fix: SQLite 迁移加版本锁,消除每次启动全量重建表
GORM sqlite AutoMigrate 对已有表判定不收敛(实测已迁移库再跑 仍触发 12 次表重建),SQLite 无在线 ALTER,每次重建走 CREATE __temp + INSERT SELECT + DROP 全表拷贝;usage_logs 含 raw_request/raw_response 大文本,一轮 40~80s,生产每次重启 重演导致启动数分钟。 - 新增 schemaVersion 常量,PRAGMA user_version 记录已迁移版本 - 版本达标跳过 AutoMigrate 秒开;旧库首次升级迁移一次写版本 - postgres 不受影响(支持 ALTER,保持原行为) - 维护约定:改表结构须递增 schemaVersion
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -11,6 +12,12 @@ import (
|
||||
gormlogger "gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
// schemaVersion 当前 schema 版本。struct 变更(加列/改列/删列)时递增,
|
||||
// 触发一次 AutoMigrate 并把新版本写入库(SQLite 用 PRAGMA user_version)。
|
||||
// AutoMigrate 对已有表的列判定不收敛(每次都重建表:CREATE __temp + INSERT SELECT + DROP),
|
||||
// 大表上一次重建数十秒且每次重启重演,所以之后版本未变就直接跳过。
|
||||
const schemaVersion = 1
|
||||
|
||||
// Open 打开数据库连接并自动迁移。
|
||||
// 开发默认 SQLite(dsn 支持 file:...?_journal_mode=WAL),生产可切 postgres。
|
||||
func Open(driver, dsn string) (*gorm.DB, error) {
|
||||
@@ -33,13 +40,33 @@ func Open(driver, dsn string) (*gorm.DB, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if driver != "postgres" && currentSQLiteVersion(db) >= schemaVersion {
|
||||
log.Printf("store: connected driver=%s (schema up-to-date v%d, skip migrate)", driver, schemaVersion)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(AllModels()...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("store: connected driver=%s (migrated)", driver)
|
||||
if driver != "postgres" {
|
||||
setSQLiteVersion(db, schemaVersion)
|
||||
}
|
||||
log.Printf("store: connected driver=%s (migrated, schema v%d)", driver, schemaVersion)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// currentSQLiteVersion 读取 PRAGMA user_version。
|
||||
func currentSQLiteVersion(db *gorm.DB) int {
|
||||
var v int
|
||||
db.Raw("PRAGMA user_version").Scan(&v)
|
||||
return v
|
||||
}
|
||||
|
||||
// setSQLiteVersion 写入 PRAGMA user_version。
|
||||
func setSQLiteVersion(db *gorm.DB, v int) {
|
||||
db.Exec(fmt.Sprintf("PRAGMA user_version = %d", v))
|
||||
}
|
||||
|
||||
// sqliteDir 提取 SQLite DSN 中的目录部分(忽略 file: 前缀与查询参数)。
|
||||
func sqliteDir(dsn string) string {
|
||||
d := dsn
|
||||
|
||||
Reference in New Issue
Block a user