随着全网扫描项目的开发,越来越细致的问题暴露出来,从能用到用的好,还有很长的路要走。

这个问题前段时间就发现了,程序一般跑个一天会越来越慢,直到某个时候程序彻底崩了,而且最后的报错也一般是mysql的报错:

pymysql.err.OperationalError: (2013, 'Lost connection to MySQL server during query ([Errno 104] Connection reset by peer)')

我突然意识到,并不是程序有问题,否则也不会跑这么长时间,而是与数据的连接不稳定导致,而之所以与数据库连接不稳定是因为程序有大量的web请求与mysql插入与查询请求。

之所以会越来越慢是因为一开始所有线程都还是存活状态,但是当某个线程遇到mysql连接出了问题的时候 该线程会立刻死掉,mysql连接问题会是间歇性的,所以线程都开始慢慢死掉,当最后一个线程死掉的时候主线程也就结束了。

前期的解决方案

最开始我用的是简单的方案,所有线程都用的是一个mysql连接,从始至终只有这一个连接,这个连接断掉,程序也就over。

后来我开始在每次执行一个sql的时候都单独建立一个mysql连接,执行完就close掉,很明显这样的问题在于,频繁连接,断开mysql,这样是相当消耗系统资源的,而且增加了mysql连接失败的几率,所以万一哪个线程没有连接成功 这个线程也over了。

最终解决方案:DBUtils

最终的解决方案还是用了数据库连接池,而且个人觉得这是个相当完美的方案。

在介绍模块的使用方法之前还是先说下原理:

1.在程序创建连接的时候,可以从一个空闲的连接中获取,不需要重新初始化连接,提升获取连接的速度
2.关闭连接的时候,把连接放回连接池,而不是真正的关闭,所以可以减少频繁地打开和关闭连接

DBUtils模块demo

下载地址:https://pypi.python.org/pypi/DBUtils/

直接上一个直观的demo,算是给自己的一个备忘

import pymysql
from DBUtils.PooledDB import PooledDB
pool = PooledDB(pymysql,50,host='localhost',user='root',passwd='pwd',db='myDB',port=3306 charset="utf8") #5为连接池里的最少连接数
conn = pool.connection() #以后每次需要数据库连接就是用connection()函数获取连接就好了
cur=conn.cursor()
SQL="select * from table1"
r=cur.execute(SQL)
r=cur.fetchall()
cur.close()
conn.close()