package database import ( "fmt" "log" "os" "time" "carrotskin/pkg/config" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" ) // New 创建新的PostgreSQL数据库连接 func New(cfg config.DatabaseConfig) (*gorm.DB, error) { dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s TimeZone=%s", cfg.Host, cfg.Port, cfg.Username, cfg.Password, cfg.Database, cfg.SSLMode, cfg.Timezone, ) // 配置慢查询监控 newLogger := logger.New( log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ SlowThreshold: 200 * time.Millisecond, // 慢查询阈值:200ms LogLevel: logger.Warn, // 只记录警告和错误 IgnoreRecordNotFoundError: true, // 忽略记录未找到错误 Colorful: false, // 生产环境禁用彩色 }, ) // 打开数据库连接 db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: newLogger, DisableForeignKeyConstraintWhenMigrating: true, // 禁用外键约束 PrepareStmt: true, // 启用预编译语句缓存 QueryFields: true, // 明确指定查询字段 }) if err != nil { return nil, fmt.Errorf("连接PostgreSQL数据库失败: %w", err) } // 获取底层SQL数据库实例 sqlDB, err := db.DB() if err != nil { return nil, fmt.Errorf("获取数据库实例失败: %w", err) } // 优化连接池配置 maxIdleConns := cfg.MaxIdleConns if maxIdleConns <= 0 { maxIdleConns = 10 } maxOpenConns := cfg.MaxOpenConns if maxOpenConns <= 0 { maxOpenConns = 100 } connMaxLifetime := cfg.ConnMaxLifetime if connMaxLifetime <= 0 { connMaxLifetime = 1 * time.Hour } connMaxIdleTime := cfg.ConnMaxIdleTime if connMaxIdleTime <= 0 { connMaxIdleTime = 10 * time.Minute } sqlDB.SetMaxIdleConns(maxIdleConns) sqlDB.SetMaxOpenConns(maxOpenConns) sqlDB.SetConnMaxLifetime(connMaxLifetime) sqlDB.SetConnMaxIdleTime(connMaxIdleTime) // 测试连接 if err := sqlDB.Ping(); err != nil { return nil, fmt.Errorf("数据库连接测试失败: %w", err) } return db, nil } // GetDSN 获取数据源名称 func GetDSN(cfg config.DatabaseConfig) string { return fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s TimeZone=%s", cfg.Host, cfg.Port, cfg.Username, cfg.Password, cfg.Database, cfg.SSLMode, cfg.Timezone, ) }