db/mysql_connector.go
2023-04-12 15:58:25 +08:00

104 lines
3.1 KiB
Go

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,
}
}