最近项目中用到sqlalchemy来作为orm框架,数据库引擎用的是pymysql,demo做出来之后,调用一个数据录入功能的API偶尔发现会出现500错误,查看后台日志在API执行过程中报了“MySQL server has gone away”错误,起初认为是数据有问题,但是后来经过调试,同一份数据有的时候可以执行有的时候就报错。所以怀疑还是sqlalchemy中的问题,相关代码如下,
engine = create_engine(db_url, echo=False)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base(engine)
这是官网上给出的最简单的连接创建方式,继续读文档发现sqlalchemy默认会维持一个5个连接的数据库连接池,而池里面的连接默认是永不失效!也就意味着如果数据库方面或者网关把连接断掉了,池里面的连接就会变成一个无效连接,继而出现开头遇到的这个问题。于是修改连接参数,加入“pool_recycle=60”表示池中的连接只维持1分钟时间,超出1分钟的连接会被弃用用新连接来代替,修改过后服务一切正常。
db_url = "mysql+pymysql://root:password@localhost:3306/third_eye?charset=utf8mb4"
engine = create_engine(db_url, echo=False, pool_recycle=7200)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base(engine)
文中的60秒超时时间并不是一个绝对合理的值,需要根据业务环境来配置,mysql默认的连接超时时间是8小时,但是我们实际环境中测出来的超时时间远远小于8小时,所以有可能是网关之类的设施将连接关闭的,但是并没有具体确认。所以理论上来说,pool_recycle的值只要小于环境中连接关闭的最小间隔就可以了。
转发文章之外PS:
mysql默认的wait_timeout=28800,也就是8个小时,一般夜间,我们服务器就处于静止状态,因此,8小时候之后mysql连接就会自动关闭,因而导致此问题。