异想天开

What's the true meaning of light, Could you tell me why

sqlalchemy超时问题排查

日期:2020-05-29 00:31:30
  
最后更新日期:2020-05-30 22:57:58
最先自己实现了一个python的数据库操作的orm类,后来觉得不太完善,如果完善就会需要加入一些sqlalchemy类似的特性,索性切换到sqlalchemy上了。刚开始切换的时候,踩了几个坑。这次将数据库迁移到云上数据库后,发现拉取列表的时候,比之前单机数据库的超时次数增加了。于是开始定位:
1.首先查看日志,发现日志里面出现了[Errno 32] Broken pipe。顿时联想,是不是向一个对端已经关闭的管道写入内容。这里其实加了try catch的,为了保险,于是对SIGPIPE信号进行忽略。
import signal
signal.signal(signal.SIGPIPE, signal.SIG_IGN)

2.但还是会小概率遇到页面超时?
看了一下nginx读取cgi的内容,超时时间为20s。于是对拉取列表请求统计耗时。耗时上来,大部分情况下,耗时比较正常,可以在100ms内完成,差的情况, 却出现了100s, 300s这样的情况。于是觉得是云上数据库不稳定,因为之前单机数据库的时候,没有出现过这种情况。


3. 那怎么解决呢? 第一步先调低了超时时间,主要是考虑用户体验,20s太长了,前端设置6s超时,数据库设置2s超时。但是这样,治标不治本。这里还是得提一下,友商的数据库治理服务,确实做得不错。利用 数据库治理的实例会话功能,可以查看到当前卡住的会话, 是在执行什么sql。 拉取列表一次,会有一个join表操作来获取内容的sql,外加20个写日志的sql。这次卡的正是这20条记录sql。 于是先去掉了记录日志的sql,情况立马缓和了。

4. 为什么会这么慢呢?
查看了一下表结构,存储引擎为INNODB,原先为MYISAM。也就是云上数据库,无视了建表语句,直接用了默认的存储引擎, 查看了云上5.7 mysql数据库只有INNODB一种存储引擎。并发写INNODB的某个表容易超时。 原因猜测为单次请求的时候,写了20条记录的事务,前端用户并发请求,造成了死锁。解决办法,kill掉死锁的线程,去掉通过sql写日志的逻辑,直接追加到文件。