Scert/backend/internal/database/mysql_pool.go

84 lines
2.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package database
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"runtime"
"time"
"github.com/go-sql-driver/mysql"
)
const mysqlReuseProbeTimeout = 2 * time.Second
func openMySQLPool(dsn string) (*sql.DB, error) {
cfg, err := mysql.ParseDSN(dsn)
if err != nil {
return nil, fmt.Errorf("解析 MySQL 连接池配置失败")
}
connector, err := mysql.NewConnector(cfg)
if err != nil {
return nil, fmt.Errorf("创建 MySQL 连接器失败")
}
// 驱动在 Windows 上没有空闲套接字检查;Linux 继续使用驱动原有检查,避免额外往返。
if runtime.GOOS == "windows" && cfg.CheckConnLiveness {
connector = &mysqlPoolConnector{Connector: connector}
}
return sql.OpenDB(connector), nil
}
// 保留锁定驱动实现的全部连接接口,不能因包装丢失事务选项、参数转换或上下文支持。
type mysqlDriverConn interface {
driver.Conn
driver.ConnBeginTx
driver.ConnPrepareContext
driver.Execer
driver.ExecerContext
driver.Queryer
driver.QueryerContext
driver.NamedValueChecker
driver.Pinger
driver.SessionResetter
driver.Validator
}
type mysqlPoolConnector struct {
driver.Connector
}
func (c *mysqlPoolConnector) Connect(ctx context.Context) (driver.Conn, error) {
conn, err := c.Connector.Connect(ctx)
if err != nil {
return nil, err
}
full, ok := conn.(mysqlDriverConn)
if !ok {
_ = conn.Close()
return nil, fmt.Errorf("MySQL 驱动连接接口不兼容")
}
return &mysqlPoolConn{mysqlDriverConn: full}, nil
}
type mysqlPoolConn struct {
mysqlDriverConn
}
func (c *mysqlPoolConn) ResetSession(ctx context.Context) error {
if err := c.mysqlDriverConn.ResetSession(ctx); err != nil {
return err
}
probeCtx, cancel := context.WithTimeout(ctx, mysqlReuseProbeTimeout)
defer cancel()
if err := c.mysqlDriverConn.Ping(probeCtx); err != nil {
_ = c.mysqlDriverConn.Close()
// 仅在业务语句发送前淘汰连接;不得把执行或提交错误改成可重试错误。
return driver.ErrBadConn
}
return nil
}
var _ driver.Connector = (*mysqlPoolConnector)(nil)
var _ mysqlDriverConn = (*mysqlPoolConn)(nil)