update
This commit is contained in:
281
mymysql/mysql.go
281
mymysql/mysql.go
@@ -1,150 +1,203 @@
|
||||
package mymysql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.makemake.in/kzkzzzz/mycommon/mylog"
|
||||
"git.makemake.in/kzkzzzz/mycommon/myconf"
|
||||
driverMysql "github.com/go-sql-driver/mysql"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
gormLogger "gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/logger"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const DefaultKey = "default"
|
||||
const (
|
||||
DefaultInstance = "mysql"
|
||||
)
|
||||
|
||||
type MysqlDb struct {
|
||||
*gorm.DB
|
||||
SqlDB *sql.DB
|
||||
gormConfig *gorm.Config
|
||||
disablePing bool
|
||||
}
|
||||
|
||||
type Conf struct {
|
||||
Dsn string
|
||||
MaxOpenConn int // 最大连接数
|
||||
MaxIdleConn int // 最大空闲连接数
|
||||
MaxIdleTime string // 空闲时间
|
||||
MaxLifeTime string // 连接最大有效时间
|
||||
Debug bool
|
||||
LogSqlSlowTimeMs int
|
||||
LogDisableColor bool
|
||||
}
|
||||
|
||||
var (
|
||||
DefaultConfig = &Config{
|
||||
Dsn: "root:root@tcp(127.0.0.1:3306)/?loc=Local&charset=utf8mb4&parseTime=true",
|
||||
MaxOpenConn: 32,
|
||||
MaxIdleConn: 8,
|
||||
MaxLifeTime: "4h",
|
||||
MaxIdleTime: "15m",
|
||||
Debug: true,
|
||||
GormLogger: gormLogger.Default.LogMode(gormLogger.Info),
|
||||
}
|
||||
|
||||
instanceMap = make(map[string]*gorm.DB)
|
||||
instanceMap = &sync.Map{}
|
||||
)
|
||||
|
||||
type (
|
||||
Config struct {
|
||||
Dsn string
|
||||
MaxOpenConn int
|
||||
MaxIdleConn int
|
||||
MaxIdleTime string
|
||||
MaxLifeTime string
|
||||
Debug bool
|
||||
GormLogger gormLogger.Interface
|
||||
}
|
||||
)
|
||||
|
||||
func DB(key ...string) *gorm.DB {
|
||||
var key0 string
|
||||
|
||||
if len(key) > 0 {
|
||||
key0 = key[0]
|
||||
func GetDb(name ...string) *MysqlDb {
|
||||
var instanceName string
|
||||
if len(name) > 0 {
|
||||
instanceName = name[0]
|
||||
} else {
|
||||
key0 = DefaultKey
|
||||
instanceName = DefaultInstance
|
||||
}
|
||||
|
||||
instance, ok := instanceMap[key0]
|
||||
v, ok := instanceMap.Load(instanceName)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("mysql %s not config", key0))
|
||||
panic(fmt.Errorf("mysql instance [%s] not init", instanceName))
|
||||
}
|
||||
return instance
|
||||
|
||||
return v.(*MysqlDb)
|
||||
}
|
||||
|
||||
func InitDefault(config *Config) {
|
||||
Init(DefaultKey, config)
|
||||
}
|
||||
|
||||
func Init(key string, config *Config) {
|
||||
db, err := New(config)
|
||||
// InitDb 初始化全局默认db
|
||||
func InitDb(config *myconf.Config, opts ...Opt) {
|
||||
client, err := NewDb(DefaultInstance, config, opts...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
instanceMap[key] = db
|
||||
instanceMap.Store(DefaultInstance, client)
|
||||
}
|
||||
|
||||
func New(config *Config) (*gorm.DB, error) {
|
||||
var (
|
||||
maxLifeTime, _ = time.ParseDuration(DefaultConfig.MaxLifeTime)
|
||||
maxIdleTime, _ = time.ParseDuration(DefaultConfig.MaxIdleTime)
|
||||
logger gormLogger.Interface
|
||||
)
|
||||
|
||||
if config.MaxOpenConn <= 0 {
|
||||
config.MaxOpenConn = DefaultConfig.MaxOpenConn
|
||||
}
|
||||
|
||||
if config.MaxIdleConn <= 0 {
|
||||
config.MaxIdleConn = DefaultConfig.MaxIdleConn
|
||||
}
|
||||
|
||||
if config.MaxLifeTime != "" {
|
||||
t, err := time.ParseDuration(config.MaxLifeTime)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse MaxLifeTime err: %s\n", err)
|
||||
|
||||
}
|
||||
maxLifeTime = t
|
||||
}
|
||||
|
||||
if config.MaxIdleTime != "" {
|
||||
t, err := time.ParseDuration(config.MaxIdleTime)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse MaxIdleTime err: %s\n", err)
|
||||
}
|
||||
maxIdleTime = t
|
||||
}
|
||||
|
||||
if config.GormLogger == nil {
|
||||
level := gormLogger.Warn
|
||||
if config.Debug {
|
||||
level = gormLogger.Info
|
||||
}
|
||||
logger = DefaultGormLogger(level)
|
||||
}
|
||||
|
||||
db, err := gorm.Open(mysql.Open(config.Dsn), &gorm.Config{
|
||||
SkipDefaultTransaction: true,
|
||||
Logger: logger,
|
||||
})
|
||||
|
||||
// InitDbInstance 初始化全局的db
|
||||
func InitDbInstance(instanceName string, config *myconf.Config, opts ...Opt) {
|
||||
client, err := NewDb(instanceName, config, opts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("connect mysql err: %s", err)
|
||||
panic(err)
|
||||
}
|
||||
sqlDb, _ := db.DB()
|
||||
instanceMap.Store(instanceName, client)
|
||||
}
|
||||
|
||||
sqlDb.SetMaxOpenConns(config.MaxOpenConn)
|
||||
sqlDb.SetMaxIdleConns(config.MaxIdleConn)
|
||||
sqlDb.SetConnMaxLifetime(maxLifeTime)
|
||||
sqlDb.SetConnMaxIdleTime(maxIdleTime)
|
||||
func NewDb(instanceName string, config *myconf.Config, opts ...Opt) (*MysqlDb, error) {
|
||||
cf := &Conf{Debug: true}
|
||||
err := config.UnmarshalKey(instanceName, &cf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db, err := NewDbFromConf(cf, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
instanceMap.Store(instanceName, db)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func NewDbFromConf(cf *Conf, opts ...Opt) (*MysqlDb, error) {
|
||||
parseDsn, err := driverMysql.ParseDSN(cf.Dsn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("mysql parse dsn error: %s", err)
|
||||
}
|
||||
|
||||
db := &MysqlDb{}
|
||||
for _, opt := range opts {
|
||||
opt(db)
|
||||
}
|
||||
|
||||
if db.gormConfig == nil {
|
||||
db.gormConfig = &gorm.Config{
|
||||
SkipDefaultTransaction: true,
|
||||
}
|
||||
|
||||
lCfg := logger.Config{
|
||||
SlowThreshold: 200 * time.Millisecond,
|
||||
LogLevel: logger.Warn,
|
||||
IgnoreRecordNotFoundError: false,
|
||||
Colorful: true,
|
||||
}
|
||||
|
||||
if cf.LogSqlSlowTimeMs > 0 {
|
||||
lCfg.SlowThreshold = time.Duration(cf.LogSqlSlowTimeMs) * time.Millisecond
|
||||
}
|
||||
|
||||
if cf.LogDisableColor {
|
||||
lCfg.Colorful = false
|
||||
}
|
||||
|
||||
l := newGormLogger(lCfg)
|
||||
|
||||
if cf.Debug {
|
||||
db.gormConfig.Logger = l.LogMode(logger.Info)
|
||||
} else {
|
||||
db.gormConfig.Logger = l
|
||||
}
|
||||
}
|
||||
|
||||
gormDB, err := gorm.Open(mysql.Open(cf.Dsn), db.gormConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sqlDB, err := gormDB.DB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if db.disablePing == false {
|
||||
err = sqlDB.Ping()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if cf.MaxOpenConn <= 0 {
|
||||
cf.MaxOpenConn = 1024
|
||||
}
|
||||
|
||||
if cf.MaxIdleConn <= 0 {
|
||||
// 默认最大空闲数等于最大连接数
|
||||
cf.MaxIdleConn = cf.MaxOpenConn
|
||||
}
|
||||
|
||||
if cf.MaxIdleTime == "" {
|
||||
cf.MaxIdleTime = "10m"
|
||||
}
|
||||
|
||||
sqlDB.SetMaxOpenConns(cf.MaxOpenConn)
|
||||
sqlDB.SetMaxIdleConns(cf.MaxIdleConn)
|
||||
|
||||
if dv, err := time.ParseDuration(cf.MaxIdleTime); err != nil {
|
||||
return nil, fmt.Errorf("parse MaxIdleTime err: %s", err)
|
||||
} else {
|
||||
sqlDB.SetConnMaxIdleTime(dv)
|
||||
}
|
||||
|
||||
// max life time默认暂不设置, 使用idle time控制即可
|
||||
if cf.MaxLifeTime != "" {
|
||||
if dv, err := time.ParseDuration(cf.MaxLifeTime); err != nil {
|
||||
return nil, fmt.Errorf("parse MaxLifeTime err: %s", err)
|
||||
} else {
|
||||
sqlDB.SetConnMaxLifetime(dv)
|
||||
}
|
||||
}
|
||||
|
||||
db.DB = gormDB
|
||||
|
||||
db.SqlDB = sqlDB
|
||||
instanceMap.Store(uuid.New().String(), db)
|
||||
|
||||
log.Printf("connect db success [addr:%s - db:%s]", parseDsn.Addr, parseDsn.DBName)
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func DefaultGormLogger(level gormLogger.LogLevel) gormLogger.Interface {
|
||||
return gormLogger.New(mylog.NewLogger("gorm", mylog.DefaultConfig), gormLogger.Config{
|
||||
SlowThreshold: time.Second * 2,
|
||||
Colorful: true,
|
||||
IgnoreRecordNotFoundError: false,
|
||||
ParameterizedQueries: false,
|
||||
LogLevel: level,
|
||||
func CloseAll() {
|
||||
instanceMap.Range(func(k, v any) bool {
|
||||
db, err := (v.(*MysqlDb)).DB.DB()
|
||||
if err != nil {
|
||||
db.Close()
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func NewGormLogger(writer gormLogger.Writer, gormLoggerConfig gormLogger.Config) gormLogger.Interface {
|
||||
return gormLogger.New(writer, gormLoggerConfig)
|
||||
}
|
||||
|
||||
func CloseDB(key string) {
|
||||
db, _ := DB(key).DB()
|
||||
db.Close()
|
||||
}
|
||||
|
||||
func CloseAllDB() {
|
||||
for _, v := range instanceMap {
|
||||
db, _ := v.DB()
|
||||
db.Close()
|
||||
}
|
||||
func newGormLogger(cfg logger.Config) logger.Interface {
|
||||
return logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), cfg)
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package mymysql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMysql(t *testing.T) {
|
||||
err := InitDefault(&Config{
|
||||
Dsn: "root:Tqa129126@tcp(119.29.187.200:3306)/site?loc=Local&charset=utf8mb4&writeTimeout=3s&readTimeout=3s&timeout=2s&parseTime=true",
|
||||
MaxOpenConn: 16,
|
||||
MaxIdleConn: 4,
|
||||
MaxIdleTime: "5m",
|
||||
MaxLifeTime: "30m",
|
||||
Debug: false,
|
||||
GormLogger: nil,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
defer CloseAllDB()
|
||||
|
||||
var res = make(map[string]interface{})
|
||||
err = DB().Table("image").Limit(1).Take(&res).Error
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%+v\n", res)
|
||||
}
|
||||
17
mymysql/option.go
Normal file
17
mymysql/option.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package mymysql
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Opt func(m *MysqlDb)
|
||||
|
||||
func WithDisablePing(v bool) Opt {
|
||||
return func(m *MysqlDb) {
|
||||
m.disablePing = v
|
||||
}
|
||||
}
|
||||
|
||||
func WithGormConfig(v *gorm.Config) Opt {
|
||||
return func(m *MysqlDb) {
|
||||
m.gormConfig = v
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user