mysql.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package database
  2. import (
  3. "fmt"
  4. "git.bvbej.com/bvbej/base-golang/pkg/errors"
  5. "gorm.io/driver/mysql"
  6. "gorm.io/gorm"
  7. "gorm.io/gorm/logger"
  8. "gorm.io/gorm/schema"
  9. "log"
  10. "os"
  11. "time"
  12. )
  13. var _ MysqlRepo = (*mysqlRepo)(nil)
  14. type MysqlRepo interface {
  15. i()
  16. GetRead() *gorm.DB
  17. GetWrite() *gorm.DB
  18. Close() error
  19. }
  20. type MySQLConfig struct {
  21. Read struct {
  22. Addr string `yaml:"addr"`
  23. User string `yaml:"user"`
  24. Pass string `yaml:"pass"`
  25. Name string `yaml:"name"`
  26. } `yaml:"read"`
  27. Write struct {
  28. Addr string `yaml:"addr"`
  29. User string `yaml:"user"`
  30. Pass string `yaml:"pass"`
  31. Name string `yaml:"name"`
  32. } `yaml:"write"`
  33. Base struct {
  34. MaxOpenConn int `yaml:"maxOpenConn"` //最大连接数
  35. MaxIdleConn int `yaml:"maxIdleConn"` //最大空闲连接数
  36. ConnMaxLifeTime time.Duration `yaml:"connMaxLifeTime"` //最大连接超时(分钟)
  37. } `yaml:"base"`
  38. }
  39. type mysqlRepo struct {
  40. read *gorm.DB
  41. write *gorm.DB
  42. }
  43. func NewMysql(cfg MySQLConfig) (MysqlRepo, error) {
  44. dbr, err := dbConnect(cfg.Read.User, cfg.Read.Pass, cfg.Read.Addr, cfg.Read.Name,
  45. cfg.Base.MaxOpenConn, cfg.Base.MaxIdleConn, cfg.Base.ConnMaxLifeTime)
  46. if err != nil {
  47. return nil, err
  48. }
  49. dbw, err := dbConnect(cfg.Write.User, cfg.Write.Pass, cfg.Write.Addr, cfg.Write.Name,
  50. cfg.Base.MaxOpenConn, cfg.Base.MaxIdleConn, cfg.Base.ConnMaxLifeTime)
  51. if err != nil {
  52. return nil, err
  53. }
  54. return &mysqlRepo{
  55. read: dbr,
  56. write: dbw,
  57. }, nil
  58. }
  59. func (d *mysqlRepo) i() {}
  60. func (d *mysqlRepo) GetRead() *gorm.DB {
  61. return d.read
  62. }
  63. func (d *mysqlRepo) GetWrite() *gorm.DB {
  64. return d.write
  65. }
  66. func (d *mysqlRepo) Close() (err error) {
  67. rdb, err1 := d.read.DB()
  68. if err1 != nil {
  69. err = errors.WithStack(err1)
  70. }
  71. err2 := rdb.Close()
  72. if err2 != nil {
  73. err = errors.WithStack(err2)
  74. }
  75. wdb, err3 := d.write.DB()
  76. if err3 != nil {
  77. err = errors.WithStack(err3)
  78. }
  79. err4 := wdb.Close()
  80. if err4 != nil {
  81. err = errors.WithStack(err4)
  82. }
  83. return err
  84. }
  85. func dbConnect(user, pass, addr, dbName string, maxOpenConn, maxIdleConn int, connMaxLifeTime time.Duration) (*gorm.DB, error) {
  86. dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=%t&loc=%s",
  87. user,
  88. pass,
  89. addr,
  90. dbName,
  91. true,
  92. "Local")
  93. // 日志配置
  94. newLogger := logger.New(
  95. log.New(os.Stdout, "\r\n", log.LstdFlags),
  96. logger.Config{
  97. SlowThreshold: time.Second, // 慢SQL阈值
  98. Colorful: true, // 彩色打印
  99. IgnoreRecordNotFoundError: true, // 忽略记录未找到错误
  100. LogLevel: logger.Error, // 日志级别
  101. },
  102. )
  103. db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
  104. NamingStrategy: schema.NamingStrategy{
  105. SingularTable: true,
  106. },
  107. Logger: newLogger,
  108. })
  109. if err != nil {
  110. return nil, errors.Wrap(err, fmt.Sprintf("[db connection failed] Database name: %s", dbName))
  111. }
  112. db.Set("gorm:table_options", "CHARSET=utf8mb4")
  113. sqlDB, err := db.DB()
  114. if err != nil {
  115. return nil, err
  116. }
  117. // 设置连接池 用于设置最大打开的连接数,默认值为0表示不限制.设置最大的连接数,可以避免并发太高导致连接mysql出现too many connections的错误。
  118. sqlDB.SetMaxOpenConns(maxOpenConn)
  119. // 设置最大连接数 用于设置闲置的连接数.设置闲置的连接数则当开启的一个连接使用完成后可以放在池里等候下一次使用。
  120. sqlDB.SetMaxIdleConns(maxIdleConn)
  121. // 设置最大连接超时
  122. sqlDB.SetConnMaxLifetime(time.Minute * connMaxLifeTime)
  123. return db, nil
  124. }