我有 2 个函数需要执行,第一个需要大约 4 个小时才能执行。两者都使用 SQLAlchemy:
def first():
session = DBSession
rows = session.query(Mytable).order_by(Mytable.col1.desc())[:150]
for i,row in enumerate(rows):
time.sleep(100)
print i, row.accession
def second():
print "going onto second function"
session = DBSession
new_row = session.query(Anothertable).order_by(Anothertable.col1.desc()).first()
print 'New Row: ', new_row.accession
first()
second()
下面是我定义 DBSession 的方式:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import create_engine
engine = create_engine('mysql://blah:blah@blah/blahblah',echo=False,pool_recycle=3600*12)
DBSession = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
Base = declarative_base()
Base.metadata.bind = engine
first() 完成得很好(大约需要 4 小时),我看到打印了“going to second function”然后它立即给我一个错误:
sqlalchemy.exc.OperationalError: (OperationalError) (2006, 'MySQL server has gone away')
通过阅读文档,我认为分配 session=DBSession 会得到两个不同的 session 实例,因此 second() 不会超时。我也试过玩 pool_recycle 但这似乎没有任何效果。在现实世界中,我不能将 first() 和 second() 拆分为 2 个脚本:second() 必须在 first() 之后立即执行
最佳答案
您的引擎(不是 session )保留一个连接池。当一个 mysql 连接数小时未被使用时,mysql 服务器关闭套接字,当您尝试使用此连接时,这会导致“Mysql server has gone away”错误。如果您有一个简单的单线程脚本,那么使用 pool_size=1
调用 create_engine
可能会达到目的。如果没有,您可以在连接从池中 check out 时使用事件对连接执行 ping 操作。这个很棒的答案包含所有详细信息:
关于python - 为什么 SQLAlchemy/mysql 总是超时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22898071/