diff --git a/wafdb/localdb.go b/wafdb/localdb.go index 93e890a..04bf540 100644 --- a/wafdb/localdb.go +++ b/wafdb/localdb.go @@ -81,87 +81,14 @@ func InitCoreDb(currentDir string) (bool, error) { //db.Use(crypto.NewCryptoPlugin()) // 注册默认的AES加解密策略 //crypto.RegisterCryptoStrategy(strategy.NewAesCryptoStrategy("3Y)(27EtO^tK8Bj~")) - // Migrate the schema - db.AutoMigrate(&model.Hosts{}) - db.AutoMigrate(&model.Rules{}) - //隐私处理 - db.AutoMigrate(&model.LDPUrl{}) - - //白名单处理 - db.AutoMigrate(&model.IPAllowList{}) - db.AutoMigrate(&model.URLAllowList{}) - - //限制处理 - db.AutoMigrate(&model.IPBlockList{}) - db.AutoMigrate(&model.URLBlockList{}) - - //抵抗CC - db.AutoMigrate(&model.AntiCC{}) - - //waf自身账号 - db.AutoMigrate(&model.TokenInfo{}) - db.AutoMigrate(&model.Account{}) - - //系统参数 - db.AutoMigrate(&model.SystemConfig{}) - - //延迟信息 - db.AutoMigrate(&model.DelayMsg{}) - - //分库信息表 - db.AutoMigrate(&model.ShareDb{}) - - //中心管控数据 - db.AutoMigrate(&model.Center{}) - - //敏感词管理 - db.AutoMigrate(&model.Sensitive{}) - - //负载均衡 - db.AutoMigrate(&model.LoadBalance{}) - - //SSL证书 - db.AutoMigrate(&model.SslConfig{}) - - //IPTag - db.AutoMigrate(&model.IPTag{}) - - //自动任务 - db.AutoMigrate(&model.BatchTask{}) - - //SSL证书申请订单 - db.AutoMigrate(&model.SslOrder{}) - - //SSL到期检测 - db.AutoMigrate(&model.SslExpire{}) - - //HTTP AUTH - db.AutoMigrate(&model.HttpAuthBase{}) - - //任务 - db.AutoMigrate(&model.Task{}) - - //自定义拦截界面 - db.AutoMigrate(&model.BlockingPage{}) - - //OTP - db.AutoMigrate(&model.Otp{}) - - //密钥信息 - db.AutoMigrate(&model.PrivateInfo{}) - - //密钥分组信息 - db.AutoMigrate(&model.PrivateGroup{}) - - //缓存规则 - db.AutoMigrate(&model.CacheRule{}) - - //隧道 - db.AutoMigrate(&model.Tunnel{}) - - //CA服务器信息 - db.AutoMigrate(&model.CaServerInfo{}) + // ============ 使用 gormigrate 替代 AutoMigrate(完全向后兼容) ============ + zlog.Info("开始执行core数据库迁移...") + if err := RunCoreDBMigrations(db); err != nil { + zlog.Error("core数据库迁移失败", "error", err) + panic("core database migration failed: " + err.Error()) + } + // ============ 迁移代码结束 ============ global.GWAF_LOCAL_DB.Callback().Query().Before("gorm:query").Register("tenant_plugin:before_query", before_query) global.GWAF_LOCAL_DB.Callback().Query().Before("gorm:update").Register("tenant_plugin:before_update", before_update) @@ -169,6 +96,7 @@ func InitCoreDb(currentDir string) (bool, error) { //重启需要删除无效规则 db.Where("user_code = ? and rule_status = 999", global.GWAF_USER_CODE).Delete(model.Rules{}) + // 执行数据补丁和默认值初始化(幂等操作,每次启动都执行) pathCoreSql(db) return isNewDb, nil } else { @@ -211,12 +139,15 @@ func InitLogDb(currentDir string) (bool, error) { //logDB.Use(crypto.NewCryptoPlugin()) // 注册默认的AES加解密策略 //crypto.RegisterCryptoStrategy(strategy.NewAesCryptoStrategy("3Y)(27EtO^tK8Bj~")) - // Migrate the schema - //统计处理 - db.AutoMigrate(&innerbean.WebLog{}) - db.AutoMigrate(&model.AccountLog{}) - db.AutoMigrate(&model.WafSysLog{}) - db.AutoMigrate(&model.OneKeyMod{}) + + // ============ 使用 gormigrate 替代 AutoMigrate(完全向后兼容) ============ + zlog.Info("开始执行log数据库迁移...") + if err := RunLogDBMigrations(db); err != nil { + zlog.Error("log数据库迁移失败", "error", err) + panic("log database migration failed: " + err.Error()) + } + // ============ 迁移代码结束 ============ + global.GWAF_LOCAL_LOG_DB.Callback().Query().Before("gorm:query").Register("tenant_plugin:before_query", before_query) global.GWAF_LOCAL_LOG_DB.Callback().Query().Before("gorm:update").Register("tenant_plugin:before_update", before_update) @@ -280,12 +211,14 @@ func InitManaulLogDb(currentDir string, custFileName string) { //logDB.Use(crypto.NewCryptoPlugin()) // 注册默认的AES加解密策略 //crypto.RegisterCryptoStrategy(strategy.NewAesCryptoStrategy("3Y)(27EtO^tK8Bj~")) - // Migrate the schema - //统计处理 - db.AutoMigrate(&innerbean.WebLog{}) - db.AutoMigrate(&model.AccountLog{}) - db.AutoMigrate(&model.WafSysLog{}) - db.AutoMigrate(&model.OneKeyMod{}) + + // ============ 使用 gormigrate 替代 AutoMigrate(完全向后兼容) ============ + zlog.Info("开始执行手动log数据库迁移...", "file", custFileName) + if err := RunLogDBMigrations(db); err != nil { + zlog.Error("手动log数据库迁移失败", "file", custFileName, "error", err) + panic("manual log database migration failed: " + err.Error()) + } + // ============ 迁移代码结束 ============ global.GDATA_CURRENT_LOG_DB_MAP[custFileName].Callback().Query().Before("gorm:query").Register("tenant_plugin:before_query", before_query) global.GDATA_CURRENT_LOG_DB_MAP[custFileName].Callback().Query().Before("gorm:update").Register("tenant_plugin:before_update", before_update) diff --git a/wafdb/migrations_core.go b/wafdb/migrations_core.go new file mode 100644 index 0000000..dd4f2d0 --- /dev/null +++ b/wafdb/migrations_core.go @@ -0,0 +1,279 @@ +package wafdb + +import ( + "SamWaf/common/zlog" + "SamWaf/model" + "fmt" + "time" + + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// RunCoreDBMigrations 执行主数据库迁移(完全兼容老用户) +func RunCoreDBMigrations(db *gorm.DB) error { + zlog.Info("开始执行core数据库迁移检查...") + + // 检测表和索引的存在情况 + tablesExist := checkCoreTablesExist(db) + indexesExist := checkCoreIndexesExist(db) + + zlog.Info("数据库状态检测", + "表是否存在", tablesExist, + "索引是否完整", indexesExist) + + m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{ + // 迁移1: 创建表(如果不存在) + { + ID: "202511140001_initial_core_tables", + Migrate: func(tx *gorm.DB) error { + if tablesExist { + zlog.Info("迁移 202511140001: 表已存在,执行结构同步") + // 表已存在,只做结构同步(安全操作,不会删除字段/数据) + if err := tx.AutoMigrate( + &model.Hosts{}, + &model.Rules{}, + &model.LDPUrl{}, + &model.IPAllowList{}, + &model.URLAllowList{}, + &model.IPBlockList{}, + &model.URLBlockList{}, + &model.AntiCC{}, + &model.TokenInfo{}, + &model.Account{}, + &model.SystemConfig{}, + &model.DelayMsg{}, + &model.ShareDb{}, + &model.Center{}, + &model.Sensitive{}, + &model.LoadBalance{}, + &model.SslConfig{}, + &model.IPTag{}, + &model.BatchTask{}, + &model.SslOrder{}, + &model.SslExpire{}, + &model.HttpAuthBase{}, + &model.Task{}, + &model.BlockingPage{}, + &model.Otp{}, + &model.PrivateInfo{}, + &model.PrivateGroup{}, + &model.CacheRule{}, + &model.Tunnel{}, + &model.CaServerInfo{}, + ); err != nil { + return fmt.Errorf("同步表结构失败: %w", err) + } + zlog.Info("表结构同步成功(数据完整保留)") + } else { + zlog.Info("迁移 202511140001: 创建新表") + // 表不存在,创建所有表 + if err := tx.AutoMigrate( + &model.Hosts{}, + &model.Rules{}, + &model.LDPUrl{}, + &model.IPAllowList{}, + &model.URLAllowList{}, + &model.IPBlockList{}, + &model.URLBlockList{}, + &model.AntiCC{}, + &model.TokenInfo{}, + &model.Account{}, + &model.SystemConfig{}, + &model.DelayMsg{}, + &model.ShareDb{}, + &model.Center{}, + &model.Sensitive{}, + &model.LoadBalance{}, + &model.SslConfig{}, + &model.IPTag{}, + &model.BatchTask{}, + &model.SslOrder{}, + &model.SslExpire{}, + &model.HttpAuthBase{}, + &model.Task{}, + &model.BlockingPage{}, + &model.Otp{}, + &model.PrivateInfo{}, + &model.PrivateGroup{}, + &model.CacheRule{}, + &model.Tunnel{}, + &model.CaServerInfo{}, + ); err != nil { + return fmt.Errorf("创建core表失败: %w", err) + } + zlog.Info("core表创建成功") + } + return nil + }, + Rollback: func(tx *gorm.DB) error { + if tablesExist { + // 如果是老数据库,不执行删除操作(保护数据) + zlog.Info("回滚 202511140001: 检测到已存在数据,跳过表删除(保护用户数据)") + return nil + } + // 新数据库可以安全删除 + zlog.Info("回滚 202511140001: 删除表") + return tx.Migrator().DropTable( + &model.Hosts{}, + &model.Rules{}, + &model.LDPUrl{}, + &model.IPAllowList{}, + &model.URLAllowList{}, + &model.IPBlockList{}, + &model.URLBlockList{}, + &model.AntiCC{}, + &model.TokenInfo{}, + &model.Account{}, + &model.SystemConfig{}, + &model.DelayMsg{}, + &model.ShareDb{}, + &model.Center{}, + &model.Sensitive{}, + &model.LoadBalance{}, + &model.SslConfig{}, + &model.IPTag{}, + &model.BatchTask{}, + &model.SslOrder{}, + &model.SslExpire{}, + &model.HttpAuthBase{}, + &model.Task{}, + &model.BlockingPage{}, + &model.Otp{}, + &model.PrivateInfo{}, + &model.PrivateGroup{}, + &model.CacheRule{}, + &model.Tunnel{}, + &model.CaServerInfo{}, + ) + }, + }, + // 迁移2: 创建索引(幂等操作) + { + ID: "202511140002_create_core_indexes", + Migrate: func(tx *gorm.DB) error { + if indexesExist { + zlog.Info("迁移 202511140002: 索引已完整,跳过创建") + return nil + } + zlog.Info("迁移 202511140002: 开始创建索引") + return createCoreIndexes(tx) + }, + Rollback: func(tx *gorm.DB) error { + zlog.Info("回滚 202511140002: 删除索引") + return dropCoreIndexes(tx) + }, + }, + }) + + // 执行迁移 + if err := m.Migrate(); err != nil { + return fmt.Errorf("core数据库迁移失败: %w", err) + } + + zlog.Info("core数据库迁移成功完成") + return nil +} + +// checkCoreTablesExist 检查核心表是否存在(检查几个关键表) +func checkCoreTablesExist(db *gorm.DB) bool { + // 检查几个关键表,如果都存在则认为是老数据库 + keyTables := []interface{}{ + &model.Hosts{}, + &model.Rules{}, + &model.Account{}, + &model.SystemConfig{}, + } + + for _, table := range keyTables { + if !db.Migrator().HasTable(table) { + return false + } + } + return true +} + +// checkCoreIndexesExist 检查所有core索引是否存在 +func checkCoreIndexesExist(db *gorm.DB) bool { + // 需要检查的索引列表(表名, 索引名) + indexes := []struct { + TableName string + IndexName string + }{ + {"ip_tags", "uni_iptags_full"}, + {"ip_tags", "idx_iptag_ip"}, + } + + for _, idx := range indexes { + if !checkIndexExists(db, idx.TableName, idx.IndexName) { + zlog.Info("索引不存在", "table", idx.TableName, "index", idx.IndexName) + return false + } + } + return true +} + +// createCoreIndexes 创建所有core索引(幂等操作) +func createCoreIndexes(tx *gorm.DB) error { + zlog.Info("开始创建core索引...") + startTime := time.Now() + + indexes := []struct { + Name string + SQL string + }{ + { + Name: "uni_iptags_full", + SQL: "CREATE UNIQUE INDEX IF NOT EXISTS uni_iptags_full ON ip_tags (user_code, tenant_id, ip, ip_tag)", + }, + { + Name: "idx_iptag_ip", + SQL: "CREATE INDEX IF NOT EXISTS idx_iptag_ip ON ip_tags (user_code, tenant_id, ip)", + }, + } + + for _, idx := range indexes { + if err := tx.Exec(idx.SQL).Error; err != nil { + return fmt.Errorf("创建索引失败 %s: %w", idx.Name, err) + } + zlog.Info("索引创建成功", "index", idx.Name) + } + + duration := time.Since(startTime) + zlog.Info("所有core索引创建完成", "耗时", duration.String()) + return nil +} + +// dropCoreIndexes 删除所有core索引 +func dropCoreIndexes(tx *gorm.DB) error { + zlog.Info("开始删除core索引") + + indexes := []string{ + "uni_iptags_full", + "idx_iptag_ip", + } + + for _, indexName := range indexes { + if err := tx.Exec(fmt.Sprintf("DROP INDEX IF EXISTS %s", indexName)).Error; err != nil { + zlog.Warn("删除索引失败(可能不存在)", "index", indexName, "error", err) + } else { + zlog.Info("索引删除成功", "index", indexName) + } + } + + zlog.Info("所有core索引删除完成") + return nil +} + +// RollbackCoreDBMigration 回滚到指定版本 +func RollbackCoreDBMigration(db *gorm.DB, migrationID string) error { + zlog.Info("准备回滚core迁移", "target_version", migrationID) + + m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{}) + if err := m.RollbackTo(migrationID); err != nil { + return fmt.Errorf("回滚失败: %w", err) + } + + zlog.Info("回滚成功完成", "version", migrationID) + return nil +} diff --git a/wafdb/migrations_log.go b/wafdb/migrations_log.go new file mode 100644 index 0000000..2b11b9d --- /dev/null +++ b/wafdb/migrations_log.go @@ -0,0 +1,231 @@ +package wafdb + +import ( + "SamWaf/common/zlog" + "SamWaf/innerbean" + "SamWaf/model" + "fmt" + "time" + + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// RunLogDBMigrations 执行日志数据库迁移(完全兼容老用户) +func RunLogDBMigrations(db *gorm.DB) error { + zlog.Info("开始执行log数据库迁移检查...") + + // 检测表和索引的存在情况 + tablesExist := checkLogTablesExist(db) + indexesExist := checkLogIndexesExist(db) + + zlog.Info("数据库状态检测", + "表是否存在", tablesExist, + "索引是否完整", indexesExist) + + m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{ + // 迁移1: 创建表(如果不存在) + { + ID: "202511140001_initial_log_tables", + Migrate: func(tx *gorm.DB) error { + if tablesExist { + zlog.Info("迁移 202511140001: 表已存在,执行结构同步") + // 表已存在,只做结构同步(安全操作,不会删除字段/数据) + if err := tx.AutoMigrate( + &innerbean.WebLog{}, + &model.AccountLog{}, + &model.WafSysLog{}, + &model.OneKeyMod{}, + ); err != nil { + return fmt.Errorf("同步表结构失败: %w", err) + } + zlog.Info("表结构同步成功(数据完整保留)") + } else { + zlog.Info("迁移 202511140001: 创建新表") + // 表不存在,创建所有表 + if err := tx.AutoMigrate( + &innerbean.WebLog{}, + &model.AccountLog{}, + &model.WafSysLog{}, + &model.OneKeyMod{}, + ); err != nil { + return fmt.Errorf("创建log表失败: %w", err) + } + zlog.Info("log表创建成功") + } + return nil + }, + Rollback: func(tx *gorm.DB) error { + if tablesExist { + // 如果是老数据库,不执行删除操作(保护数据) + zlog.Info("回滚 202511140001: 检测到已存在数据,跳过表删除(保护用户数据)") + return nil + } + // 新数据库可以安全删除 + zlog.Info("回滚 202511140001: 删除表") + return tx.Migrator().DropTable( + &innerbean.WebLog{}, + &model.AccountLog{}, + &model.WafSysLog{}, + &model.OneKeyMod{}, + ) + }, + }, + // 迁移2: 创建索引(幂等操作) + { + ID: "202511140002_create_log_indexes", + Migrate: func(tx *gorm.DB) error { + if indexesExist { + zlog.Info("迁移 202511140002: 索引已完整,跳过创建") + return nil + } + zlog.Info("迁移 202511140002: 开始创建索引") + return createLogIndexes(tx) + }, + Rollback: func(tx *gorm.DB) error { + zlog.Info("回滚 202511140002: 删除索引") + return dropLogIndexes(tx) + }, + }, + }) + + // 执行迁移 + if err := m.Migrate(); err != nil { + return fmt.Errorf("log数据库迁移失败: %w", err) + } + + zlog.Info("log数据库迁移成功完成") + return nil +} + +// checkLogTablesExist 检查所有log表是否存在 +func checkLogTablesExist(db *gorm.DB) bool { + tables := []interface{}{ + &innerbean.WebLog{}, + &model.AccountLog{}, + &model.WafSysLog{}, + &model.OneKeyMod{}, + } + + for _, table := range tables { + if !db.Migrator().HasTable(table) { + return false + } + } + return true +} + +// checkLogIndexesExist 检查所有log索引是否存在 +func checkLogIndexesExist(db *gorm.DB) bool { + // 需要检查的索引列表(表名, 索引名) + indexes := []struct { + TableName string + IndexName string + }{ + {"web_logs", "idx_web_logs_task_flag_time"}, + {"web_logs", "idx_web_time_tenant_user_code"}, + {"web_logs", "idx_req_uuid_web_logs"}, + {"web_logs", "idx_tenant_usercode_web_logs"}, + {"web_logs", "idx_web_time_desc_tenant_user_code"}, + {"web_logs", "idx_web_time_desc_tenant_user_code_ip"}, + {"web_logs", "idx_web_guest_id_entification"}, + } + + for _, idx := range indexes { + if !checkIndexExists(db, idx.TableName, idx.IndexName) { + zlog.Info("索引不存在", "table", idx.TableName, "index", idx.IndexName) + return false + } + } + return true +} + +// createLogIndexes 创建所有log索引(幂等操作) +func createLogIndexes(tx *gorm.DB) error { + zlog.Info("开始创建log索引(可能需要几分钟)...") + startTime := time.Now() + + indexes := []struct { + Name string + SQL string + }{ + { + Name: "idx_web_logs_task_flag_time", + SQL: "CREATE INDEX IF NOT EXISTS idx_web_logs_task_flag_time ON web_logs (task_flag, unix_add_time)", + }, + { + Name: "idx_web_time_tenant_user_code", + SQL: "CREATE INDEX IF NOT EXISTS idx_web_time_tenant_user_code ON web_logs (unix_add_time, tenant_id, user_code)", + }, + { + Name: "idx_req_uuid_web_logs", + SQL: "CREATE INDEX IF NOT EXISTS idx_req_uuid_web_logs ON web_logs (REQ_UUID, tenant_id, user_code)", + }, + { + Name: "idx_tenant_usercode_web_logs", + SQL: "CREATE INDEX IF NOT EXISTS idx_tenant_usercode_web_logs ON web_logs (tenant_id, user_code)", + }, + { + Name: "idx_web_time_desc_tenant_user_code", + SQL: "CREATE INDEX IF NOT EXISTS idx_web_time_desc_tenant_user_code ON web_logs (unix_add_time desc, tenant_id, user_code)", + }, + { + Name: "idx_web_time_desc_tenant_user_code_ip", + SQL: "CREATE INDEX IF NOT EXISTS idx_web_time_desc_tenant_user_code_ip ON web_logs (unix_add_time desc, tenant_id, user_code, src_ip)", + }, + { + Name: "idx_web_guest_id_entification", + SQL: "CREATE INDEX IF NOT EXISTS idx_web_guest_id_entification ON web_logs (guest_id_entification, day, is_bot, host_code)", + }, + } + + for _, idx := range indexes { + if err := tx.Exec(idx.SQL).Error; err != nil { + return fmt.Errorf("创建索引失败 %s: %w", idx.Name, err) + } + zlog.Info("索引创建成功", "index", idx.Name) + } + + duration := time.Since(startTime) + zlog.Info("所有log索引创建完成", "耗时", duration.String()) + return nil +} + +// dropLogIndexes 删除所有log索引 +func dropLogIndexes(tx *gorm.DB) error { + zlog.Info("开始删除log索引") + + indexes := []string{ + "idx_web_logs_task_flag_time", + "idx_web_time_tenant_user_code", + "idx_req_uuid_web_logs", + "idx_tenant_usercode_web_logs", + "idx_web_time_desc_tenant_user_code", + "idx_web_time_desc_tenant_user_code_ip", + "idx_web_guest_id_entification", + } + + for _, indexName := range indexes { + if err := tx.Exec(fmt.Sprintf("DROP INDEX IF EXISTS %s", indexName)).Error; err != nil { + zlog.Warn("删除索引失败(可能不存在)", "index", indexName, "error", err) + } else { + zlog.Info("索引删除成功", "index", indexName) + } + } + + zlog.Info("所有log索引删除完成") + return nil +} + +// RollbackLogDBMigration 回滚到指定版本 +func RollbackLogDBMigration(db *gorm.DB, migrationID string) error { + zlog.Info("准备回滚log迁移", "target_version", migrationID) + + m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{}) + if err := m.RollbackTo(migrationID); err != nil { + return fmt.Errorf("回滚失败: %w", err) + } + + zlog.Info("回滚成功完成", "version", migrationID) + return nil +} diff --git a/waftask/task_createindex.go b/waftask/task_createindex.go index 4b10ff7..919df2e 100644 --- a/waftask/task_createindex.go +++ b/waftask/task_createindex.go @@ -3,8 +3,6 @@ package waftask import ( "SamWaf/common/zlog" "SamWaf/enums" - "SamWaf/global" - "time" ) // TaskCreateIndex 创建索引 @@ -37,95 +35,20 @@ func TaskCreateIndexByDbName(dbName string) { } func createMainDbIndex() { - db := global.GWAF_LOCAL_DB - if db == nil { - return - } - startTime := time.Now() + // ============ 已废弃:索引创建已迁移到 gormigrate ============ + // 从 2025-11-14 开始,core 数据库索引通过 gormigrate 在数据库初始化时自动创建 + // ============================================================ - zlog.Info("ready create core index maybe use a few minutes ") - - //20241106 创建iptagtag索引 - err := db.Exec("CREATE UNIQUE INDEX IF NOT EXISTS uni_iptags_full ON ip_tags (user_code, tenant_id, ip, ip_tag)").Error - if err != nil { - panic("failed to create index : uni_iptags_full " + err.Error()) - } else { - zlog.Info("db", "uni_iptags_full created") - } - // 创建iptag ip索引 - err = db.Exec("CREATE INDEX IF NOT EXISTS idx_iptag_ip ON ip_tags ( user_code, tenant_id, ip)").Error - if err != nil { - panic("failed to create index: idx_iptag_ip " + err.Error()) - } else { - zlog.Info("db", "idx_iptag_ip created") - } - // 记录结束时间并计算耗时 - duration := time.Since(startTime) - zlog.Info("create core index completely", "duration", duration.String()) + zlog.Info("createMainDbIndex 已废弃,索引由 gormigrate 自动管理") + return } func createLogDbIndex() { - db := global.GWAF_LOCAL_LOG_DB - if db == nil { - return - } - // 20241018 创建联合索引 weblog - startTime := time.Now() + // ============ 已废弃:索引创建已迁移到 gormigrate ============ + // 从 2025-11-14 开始,log 数据库索引通过 gormigrate 在数据库初始化时自动创建 + // ============================================================ - zlog.Info("ready create log index maybe use a few minutes ") - err := db.Exec("CREATE INDEX IF NOT EXISTS idx_web_logs_task_flag_time ON web_logs (task_flag, unix_add_time)").Error - if err != nil { - panic("failed to create index: idx_web_logs_task_flag_time " + err.Error()) - } else { - zlog.Info("db", "idx_web_logs_task_flag_time created") - } - // 创建联合索引 - err = db.Exec("CREATE INDEX IF NOT EXISTS idx_web_time_tenant_user_code ON web_logs (unix_add_time, tenant_id,user_code)").Error - if err != nil { - panic("failed to create index: idx_web_time_tenant_user_code " + err.Error()) - } else { - zlog.Info("db", "idx_web_time_tenant_user_code created") - } - // 详情索引 - err = db.Exec("CREATE INDEX IF NOT EXISTS idx_req_uuid_web_logs ON web_logs (REQ_UUID, tenant_id, user_code)").Error - if err != nil { - panic("failed to create index:idx_req_uuid_web_logs " + err.Error()) - } else { - zlog.Info("db", "idx_unique_req_uuid_web_logs created") - } - // 整体索引 - err = db.Exec("CREATE INDEX IF NOT EXISTS idx_tenant_usercode_web_logs ON web_logs ( tenant_id, user_code)").Error - if err != nil { - panic("failed to create index: idx_tenant_usercode_web_logs " + err.Error()) - } else { - zlog.Info("db", "idx_tenant_usercode_web_logs created") - } - - // 20250123 创建联合索引 - err = db.Exec("CREATE INDEX IF NOT EXISTS idx_web_time_desc_tenant_user_code ON web_logs (unix_add_time desc, tenant_id,user_code)").Error - if err != nil { - panic("failed to create index: idx_web_time_desc_tenant_user_code " + err.Error()) - } else { - zlog.Info("db", "idx_web_time_desc_tenant_user_code created") - } - //20250123 建立带IP得 - err = db.Exec("CREATE INDEX IF NOT EXISTS idx_web_time_desc_tenant_user_code_ip ON web_logs (unix_add_time desc, tenant_id,user_code,src_ip)").Error - if err != nil { - panic("failed to create index: idx_web_time_desc_tenant_user_code_ip " + err.Error()) - } else { - zlog.Info("db", "idx_web_time_desc_tenant_user_code_ip created") - } - - // 2025-05-02 添加新索引:为guest_id_entification字段创建索引,优化机器人识别查询 - err = db.Exec("CREATE INDEX IF NOT EXISTS idx_web_guest_id_entification ON web_logs (guest_id_entification, day, is_bot, host_code)").Error - if err != nil { - panic("failed to create index: idx_web_guest_id_entification " + err.Error()) - } else { - zlog.Info("db", "idx_web_guest_id_entification created") - } - - // 记录结束时间并计算耗时 - duration := time.Since(startTime) - zlog.Info("create log index completely", "duration", duration.String()) + zlog.Info("createLogDbIndex 已废弃,索引由 gormigrate 自动管理") + return } func createStatDbIndex() { // ============ 已废弃:索引创建已迁移到 gormigrate ============