package db import ( // "context" "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" "strings" "time" ) type MysqlConnector struct { } func (c MysqlConnector) connect(config *DBConfig) *Connection { /** [username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN] // user@unix(/path/to/socket)/dbname // root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local // user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true // user:password@/dbname?sql_mode=TRADITIONAL // user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_unicode_ci // id:password@tcp(your-amazonaws-uri.com:3306)/dbname // user@cloudsql(project-id:instance-name)/dbname // user@cloudsql(project-id:regionname:instance-name)/dbname // user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped // user:password@/dbname // user:password@/ */ //TODO: Protocol loc readTimeout serverPubKey timeout if config.MaxOpenConns == 0 { config.MaxOpenConns = 15 } if config.MaxIdleConns == 0 { config.MaxIdleConns = 5 } if config.ConnMaxLifetime == 0 { config.ConnMaxLifetime = 86400 } if config.ConnMaxIdleTime == 0 { config.ConnMaxIdleTime = 7200 } var params []string if len(config.Charset) > 0 { params = append(params, "charset="+config.Charset) } if len(config.Collation) > 0 { params = append(params, "collation="+config.Collation) } if config.MultiStatements { params = append(params, "multiStatements=true") } if config.ParseTime { params = append(params, "parseTime=true") } var dsn string if len(config.Dsn) > 0 { dsn = config.Dsn } else { dsn = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", config.Username, config.Password, config.Host, config.Port, config.Database, strings.Join(params, "&")) } db, err := sql.Open(DriverMysql, dsn) if err != nil { panic(err.Error()) } else if err := db.Ping(); err != nil { panic(err) } else { // 最大链接数, 默认0, 不限制 db.SetMaxOpenConns(config.MaxOpenConns) // 最大空闲链接数, 默认2 db.SetMaxIdleConns(config.MaxIdleConns) // 表示在连接池中连接的最大生存时间, 默认0, 表示不限制。 db.SetConnMaxLifetime(time.Duration(config.ConnMaxLifetime) * time.Second) // 连接池中空闲连接的最大生存时间, 默认0, 表示不限制。 db.SetConnMaxIdleTime(time.Duration(config.ConnMaxIdleTime) * time.Second) } // 优化事物查询速度 // Golang 在 MYSQL 事物中不能并发执行查询, 会出现 driver:bad connection, // 为了在事物中执行并发查询, 单独开一个脏读查询链接 // 处理 driver:bad connection, 需要加锁 // 同一事务开启多协程的同时如果有并发读, 那可能会出现 driver:bad connection 错误, // 原因是同一事务同一时间只能有一个可以进行读操作, 读完之后需要将查询得到的Rows关闭. if len(params) > 0 { dsn = dsn + `&` } RxDB, err := sql.Open(DriverMysql, dsn+`transaction_isolation='read-uncommitted'`) if err != nil { panic("开启事物链接失败, " + err.Error()) } else { RxDB.SetMaxOpenConns(5) RxDB.SetMaxIdleConns(5) } return &Connection{ RxDB: RxDB, DB: db, Config: config, } }