snower / TorMySQL

The highest performance asynchronous MySQL driver by PyMySQL
MIT License
308 stars 63 forks source link

长时间无数据库操作时,出现StreamClosedError #8

Closed evolsnow closed 8 years ago

evolsnow commented 8 years ago

环境:centos+tornado+celery 配置:
max_connections=200, idle_seconds=7200, wait_connection_timeout=3,

12小时无数据库操作后,celery通过IOLoop.instance().run_sync调用数据库操作时,出现: (2006, "MySQL server has gone away (StreamClosedError('Stream is closed',))")

重启tornado解决

snower commented 8 years ago

7200秒没用使用之后会关闭连接啊,ioloop还在运行么?

evolsnow commented 8 years ago

感觉是ioloop用错了,celery的ioloop写法估计有问题。 On Wed, Jun 8, 2016 at 17:02 snower notifications@github.com wrote:

7200秒没用使用之后会关闭连接啊,ioloop还在运行么?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/snower/TorMySQL/issues/8#issuecomment-224530976, or mute the thread https://github.com/notifications/unsubscribe/AGr8z6S51EJDU6JQY3j-wz2IvK323r-oks5qJoUPgaJpZM4IwnSE .

snower commented 8 years ago

如果ioloop没有在运行的话,连接时无法知道已经断开连接的,所以再次使用时会出现这个错误,可以放下代码看看。

evolsnow commented 8 years ago

数据库操作代码:

async def execution(query, args=None):
    conn = await mysql_pool.Connection()
    with conn:
        try:
            with conn.cursor() as cursor:
                await cursor.execute(query, args)
        except Exception as e:
            await conn.rollback()
        else:
            await conn.commit()
            return cursor
    return None

超过8小时没有数据库连接(ioloop也未处理任何请求),所以应该被mysql主动断开了所有连接。

这种情况下应该是手动catch StreamClosedError后reconnect然后重试,还是说有更好的办法,谢谢。

snower commented 8 years ago

阻塞的pymysql确实有这个问题,也确实是这么解决的,但用tornado不存在啊,如果IOLoop一直是start状态的话,mysql断开连接,连接池是知道的,这时候连接池也会断开该连接,下次使用时是不会取到该连接操作的,看你在celery用IOLoop.instance().run_sync运行,难道是主进程初始化了连接池,工作进程并没有一直运行着IOLoop?一般来说你应该在IOLoop结束之前就应该关闭连接池,下次IOLoop开始运行之后初始化连接池,celery工作进程理论上来说没法让IOLoop一直运行吧,其实你直接用pymysql就行。

evolsnow commented 8 years ago

嗯 为了避免将异步数据库操作函数用同步方法再写一遍,所以在celery强行用run_sync来运行异步函数了。暂时还是为celery写一遍同步方法吧。 On Sat, Jun 11, 2016 at 16:34 snower notifications@github.com wrote:

阻塞的pymysql确实有这个问题,也确实是这么解决的,但用tornado不存在啊,如果IOLoop一直是start状态的话,mysql断开连接,连接池是知道的,这时候连接池也会断开该连接,下次使用时是不会取到该连接操作的,看你在celery用IOLoop.instance().run_sync运行,难道是主进程初始化了连接池,工作进程并没有一直运行着IOLoop?一般来说你应该在IOLoop结束之前就应该关闭连接池,下次IOLoop开始运行之后初始化连接池,celery工作进程理论上来说没法让IOLoop一直运行吧,其实你直接用pymysql就行。

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/snower/TorMySQL/issues/8#issuecomment-225344558, or mute the thread https://github.com/notifications/unsubscribe/AGr8z-yVoHJuEY9YOzC7d3nQtw8iNssMks5qKnMAgaJpZM4IwnSE .

snower commented 8 years ago

哦,这样啊,其实你可以不使用连接池,直接使用连接,然后按照对待同步的方式处理就行,连接的关闭什么的。