高级软件工程师教会小白的那些事(18)

每天早上,连接到数据库都会失败,显示error“MYSQL服务器已经消失。”有时候,下午也是如此。机器在下午转动,所以我首先检查的就是这个。不,机器转动时从未发生过错误。我们全天向数据库发出数千个请求,没有一个失败的。那么,这个非常低的负载触发怎么会失败呢?

哦,也许是因为我们没有在事务结束后关闭会话?所以,如果是相同的会话,并且下一个请求在很长一段时间后出现,我们就超时了,服务器就消失了。去看一眼代码,果然,我们在每次读取时使用上下文管理器,在__exit __()上调用session.close()。

用一整天时间来排查所有可能的故障,一无所获,第二天早上上班,机缘巧合之下找到了原因。像往常一样,那天早上也报错了,一秒后,有其他三个索引请求成功了。这符合有一个会话没有被正确关闭的所有表现。后面的故事你已经知道了。

除非你使用的是NullPool,否则SQLAlchemy的mysql语言中的Session.close()不会关闭基础数据库连接。是的,后来就把这里修好了。

好玩的是,这个bug的发生仅仅是因为,我们没有选择在晚上或午餐时间发布研究报告。这里还有另一个教训——stack overflow上的大部分答案(我当然有事先Google过了!)是调整会话超时时间,或者是调整控制每个SQL语句可以发送的数据量的参数。那些回答对我来说都讲不通,因为它们与根本性的问题几乎无关。我检查过查询大小是否在限制范围内,以确保关闭会话时不会发生超时。

推荐阅读