Merge pull request #538 from samwafgo/feat_db_modfiy

Feat db modfiy
This commit is contained in:
samwafgo
2025-11-14 11:50:38 +08:00
committed by GitHub
4 changed files with 545 additions and 179 deletions
+25 -92
View File
@@ -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)
+279
View File
@@ -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
}
+231
View File
@@ -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
}
+10 -87
View File
@@ -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 ============