MySQL 连接池
概念
官方解释:数据库连接池是程序启动时申请足够的数据库连接,由程序动态的对连接池中的数据库连接进行申请、使用和回收。
个人理解:建立数据库连接是比较耗时的操作,通过数据库连接池提前向数据库申请连接足够多的连接数,需要使用的时候不需要向数据库建立连接,而是直接从连接池中获取,降低了数据库操作的等待建立连接时间,并且连接使用完成后再由连接池进行回收,达到了连接复用的效果。
两种连接方式
- 直接与数据库建立连接:
每次操作都需要申请与数据库建立连接,并且使用完之后直接释放数据库连接,但是创建一个数据库连接需要消耗的资源、时间是比较昂贵的,并且数据库连接是有限制的,在高并发的场景下很容易导致数据库崩溃。
- 使用连接池机制:
连接池工作步骤:
- 设置参数,涉及到最大空闲连接数、最大连接数、连接最大复用时间。
- 程序启动时,连接池向数据库申请可用连接,数目为最大空闲连接数。
- 业务线程向连接池申请连接,并且使用完后返回连接池。
- 程序退出时,断开所有连接。
关键参数:
- 最大空闲连接数:连接池一直保持的连接数目,一般默认是 2,如使用默认的话,程序启动时连接池将向数据库申请两个连接并且保持。
- 最大连接数:线程池最多能申请的连接数量,默认不限制(生产环境下一定要指定),当程序向线程池申请的数量超过最大空闲连接数时,此时再申请的话,等价于通过线程池向数据库建立一个新的连接,但此连接不会立即释放,而是会被复用。当程序申请的连接数大于最大连接数时,之后的请求都会被放入等待队列中,等待其他线程的连接。
- 连接最大复用时间:此参数用于上面的请求连接数超过最大空闲连接数的情况,额外申请的连接不会立即释放,在业务线程完成操作返回后,此连接将会等待被其他线程复用,等待时间即为连接最大复用时间,等待超过此时间后,连接将被销毁。
连接池到底是什么?
从上面的内容我们不难看出,连接池其实就是程序维护的数据库连接的缓存,以便在将来需要对数据库发出请求时可以重用连接。 连接池用于提高在数据库上执行命令的性能。为每个用户打开和维护数据库连接,尤其是对动态数据库驱动的应用程序发出的请求,既昂贵又浪费资源。在连接池中,创建连接之后,将连接放在池中并再次使用,这样就不必创建新的连接。如果所有连接都正在使用,则创建一个新连接并将其添加到池中。连接池还减少了用户必须等待创建与数据库的连接的时间,并且通过设置最大连接数,能够保护数据库,防止出现连接数过多而导致数据库变慢甚至奔溃的情况。
代码实践
目前 Go 最常用的 ORM 框架如 XORM 和 GORM 都支持连接池,接下来将会以 XORM 为例,写一个 Go 使用连接池操作 MySQL 的小 demo。
func InitMysqlHandler(conf MysqlConfig) error {
var (
err error
)
dataSource := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", conf.Username, conf.Password, conf.Host, conf.Port, conf.DBName)
engine, err := xorm.NewEngine("mysql", dataSource)
if err != nil {
return err
}
engine.ShowSQL(true)
engine.ShowExecTime(true)
engine.SetMaxOpenConns(conf.MaxOpenConn) // 设置连接池最大打开连接数
engine.SetMaxIdleConns(conf.MaxIdleConn) // 设置连接池最大空闲连接数
engine.SetConnMaxLifetime(10 * time.Second) // 设置连接最大复用时间
engine.SetMapper(core.LintGonicMapper)
err = engine.Ping()
if err != nil {
return err
}
mysqlHandler = &MysqlHandler{
engine: engine,
}
return nil
}
xorm 默认即开启连接池,通过查看源码得知
// SetMaxIdleConns set the max idle connections on pool, default is 2 func (engine *Engine) SetMaxIdleConns(conns int) { engine.db.SetMaxIdleConns(conns) }
默认最大空闲连接数是 2
func NewSession() *xorm.Session { return mysqlHandler.engine.NewSession() }
每次需要执行 DB 操作的时候,engine.NewSession() 就是从连接池中取一个连接出来使用,使用完记得调用 session.close() 将连接返回池中。
总结
本文介绍了数据库连接池的概念,并且通过使用 go xorm 框架简单介绍了连接池的定义与使用。欢迎前往我的 github 仓库查看源码,有问题可以评论区讨论。