一.sqlalchemy连接池
我写了一个简单的内网dns管理系统,用到flask和sqlalchemy。主要就是通过web页面和api对dns记录进行增删改查,所有这些操作都写入数据库,每次更改后产生一个celery任务来异步的重新生成dns的配置文件。
看起来一个简单的问题,但是在celery中读取数据库的时候出现了问题,每天早上都会报错Mysql has gone away,我重启服务恢复正常,第二天早上又会出现同样的问题,但是在flask的路由下调用的所有数据库操作从未出现任何问题。咨询DBA,DBA说数据库是正常的,所以一定是我的程序处理有问题了。我在网上各种资料查询,最后找到结果。
flask_sqlalchemy默认使用数据库连接池来对理数据库连接进行复用以减少建立连接的开销,他默认会对连接池中的每个连接隔2小时检查一次是否可用,如果不可用就销毁掉,创建新的连接放到连接池中,我们使用db.session的时候就需要从连接池中拿到一个连接,使用完后调用db.session.close来将连接放回到连接池(close并不是关闭连接,关闭连接的操作由连接池来管理)。但是我在路由函数中从来没有使用过db.session.close,也从来没有出现过问题,是因为flask_sqlachemy会自动在请求上下文结束时自动将连接放回连接池,这样放回连接池的连接就会每隔两小时接受一次检查。但是在celery中查询的时候问题就会出现,celery中并没有请求上下文,所有查询完以后并不会将连接放回连接池,也就是说celery中一直使用同一个连接,从来没有放回过连接池,也就从来不会被检查连接的有效性,所以连接断开的时候进行查询,导致报错。
连接为什么会断