环境:bae基础版(SAE上面也可以用,方法就是sae上面的)flask,MYSQLdb

下面👇有非 sae 环境

新浪的方法:http://www.sinacloud.com/doc/sae/python/faq.html#mysql-gone-away

newuser=User(form.firstname.data,form.lastname.data,form.email.data,form.password.data)

db.session.add(newuser)  
db.session.commit()  
db.session.close()  

添加红色的代码,注册完成之后关闭服务器连接。

新浪中说明了更改的方法:

MySQL连接超时时间为30s,不是默认的8小时,所以你需要在代码中检查是否超时,是否需要重连。

对于使用sqlalchemy的用户,需要在请求处理结束时调用 db.session.close() ,关闭当前session,将mysql连接还给连接池,并且将连接池的连接recyle时间设的小一点(推荐为10s)。

调整recyle 的方法:

SQLALCHEMYPOOLRECYCLE = 10(写在配置文件中或者传入SQLAlchemy中)

app.config.from_object(‘config’)

db = SQLAlchemy(app)  

即可解决长链接数据库断开的问题。

非 sae 环境 createengine()函数和连接池相关的参数有:
-pool
recycle, 默认为-1, 推荐设置为7200, 即如果connection空闲了7200秒, 自动重新获取, 以防止connection被db server关闭.

-pool_size=5, 连接数大小,默认为5,正式环境该数值太小,需根据实际情况调大

-maxoverflow=10, 超出poolsize后可允许的最大连接数,默认为10, 这10个连接在使用过后, 不放在pool中, 而是被真正关闭的.

-pool_timeout=30, 获取连接的超时阈值, 默认为30秒

直接只用create_engine 时,就会创建一个带连接池的引擎

engine = create_engine('postgresql://postgres@127.0.0.1/dbname')  

当使用session后就显示地调用session.close(),也不能把连接关闭,连接由QueuePool连接池管理并复用

引发问题

当数据库重启,最初保持的连接就会失败,随后进行session.query() 就会失败抛出异常 mysql 数据 ,interactive_timeout等参数处理连接的空闲时间超过(配置时间),断开。

禁用SQLAlchemy提供的数据库连接池,只需要在调用create_engine是指定连接池为NullPool,SQLAlchemy就会在执行session.close()后立刻断开数据库连接。

sqlalchemy 推荐方法:

from sqlalchemy.orm import sessionmaker  
from sqlalchemy import create_engine  
from flask import Flask  
from sqlalchemy import exc  
from sqlalchemy import event  
from sqlalchemy import select

app = Flask(__name__)  
app.config.from_object('config')  
engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'], pool_recycle=3600)  
Session = sessionmaker(bind=engine)


@event.listens_for(engine, "engine_connect")
def ping_connection(connection, branch):  
    '''
    数据库 session 连接检测事件, 断开之后在这里重新连接

    :param connection: session 连接对象
    :param branch: 数据库连接的子连接
    :return: 不返回数据
    '''

    if branch:
        return
    try:
        connection.scalar(select([1]))
    except exc.DBAPIError as err:
        if err.connection_invalidated:
            connection.scalar(select([1]))
        else:
            raise

在使用的时候:

session = Session()  
*******************
session.close()  

然后在其他文件中 import session 就好了