Orm SQLAlchemy+;PyMysql:如何从陈旧的连接错误中恢复(PyMysql.err.InternalError)
很明显,我似乎遗漏了一些东西:我希望SQLAlchemy通过在“签出”时重新创建旧连接来从旧连接中恢复 我的应用程序使用SQLAlchemy ORM(严格来说是ORM,根本不使用表达式语言)连接并与MYSQL数据库通信。当一段时间内没有活动时,池中的连接似乎过时并生成Orm SQLAlchemy+;PyMysql:如何从陈旧的连接错误中恢复(PyMysql.err.InternalError),orm,sqlalchemy,pymysql,Orm,Sqlalchemy,Pymysql,很明显,我似乎遗漏了一些东西:我希望SQLAlchemy通过在“签出”时重新创建旧连接来从旧连接中恢复 我的应用程序使用SQLAlchemy ORM(严格来说是ORM,根本不使用表达式语言)连接并与MYSQL数据库通信。当一段时间内没有活动时,池中的连接似乎过时并生成 sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1046, 'No database selected') 我尝试过设置预ping,也在create_引擎中
sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1046, 'No database selected')
我尝试过设置预ping,也在create_引擎中设置了pool_recycle
我创建了一个示例来测试这一点:请注意,pool_recycle非常积极,可以更快地尝试产生错误情况(在我的应用程序中,它是3600)
#我的测试程序在.py文件中
#-完全工作的代码-但在create_引擎中替换name/pwd/Dbserver
从sqlalchemy.ext.declarative导入声明性基础
从sqlalchemy.orm导入sessionmaker
从sqlalchemy导入创建引擎、事件、exc
从sqlalchemy导入元数据、列、整数、日期时间
从日期时间导入日期时间
从时间上导入睡眠
导入pymysql
引擎=创建引擎('mysql+pymysql://name:pwd@127.0.0.1',
池\u pre\u ping=True,池\u recycle=1)
会话=会话生成器(绑定=引擎)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
execute('DROP DATABASE IF EXISTS satest')
#创建并使用数据库
execute('CREATE DATABASE IF NOT exist satest')
engine.execute('USE satest')
#准备创建表
元数据=元数据(引擎)
#session=scoped_session(sessionmaker(bind=engine))
base=声明性_base()
TblFoo类(基本类):
__tablename_uuu='Foo'
id=列(整数,主键=True,可空=False)
计数器=列(整数)
dateTime=列(dateTime)
def createFooRecords():
计数=1
当计数小于1000000时:
realCount=count
尝试:
全球会议
会话=会话()
rec=TblFoo(计数器=计数,
dateTime=dateTime.today().isoformat())
会话.添加(rec)
session.commit()
计数+=1
最后:
session.close()
如果realCount!=计数:
睡眠(realCount*5)
@事件。侦听(引擎,“处理错误”)
def接收处理错误(异常上下文):
打印('句柄错误:',异常\u上下文)
如果isinstance(异常\u上下文.original\u异常,
pymysql.err.InternalError):
如果str(异常上下文原始异常)='1046':
打印('内部错误:')
其他:
print('某些其他错误:',
异常(上下文。原始异常)
@事件。侦听(引擎“失效”)
def接收失效(dbapi连接、连接记录、异常):
打印('DBAPI连接:',DBAPI_连接)
打印('连接记录:',连接记录)
打印('异常:',异常)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
base.metadata.create_all(引擎)
createFooRecords()
当然,engine.pool中的连接在1秒后超时,第二次调用session.add(rec)失败
“handle_error”确实会被调用
Handle Error: <sqlalchemy.engine.base.ExceptionContextImpl object at 0x1093311d0>
Some other error: (1046, 'No database selected')
Traceback (most recent call last):
.... stacktrace omitted for brevity, finally ....
ssqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1046, 'No database selected') [SQL: 'INSERT INTO `Foo` (counter, `dateTime`) VALUES (%(counter)s, %(dateTime)s)'] [parameters: {'counter': 2, 'dateTime': '2019-08-28T15:07:45.184456'}] (Background on this error at: http://sqlalche.me/e/2j85)
处理错误:
其他一些错误:(1046,“未选择数据库”)
回溯(最近一次呼叫最后一次):
.... 为了简洁起见,最后省略了stacktrace。。。。
ssqlachemy.exc.InternalError:(pymysql.err.InternalError)(1046,'未选择数据库')[SQL:'插入'Foo'(计数器,`dateTime`)值(%%(计数器)s,%%(dateTime)s)][参数:{'counter':2,'dateTime':'2019-08-28815:07:45.184456'(此错误的背景信息位于:http://sqlalche.me/e/2j85)
“无效”永远不会被调用
那么,SQLAlchemy为什么不重新创建连接,因为它很清楚它会在1秒内过期(pool_recycle value)。(不清楚它是否正在进行预ping-如何验证?--但如果发生,它仍然没有重新创建连接。)
诚然,错误来自PyMysql,但设置在SQLAlchemy中
当然,我希望这是可恢复的,所以我在try-catch中添加了一个except:但也许重新创建引擎不是正确的方法
def createFooRecords():
count = 1
while count < 1000000:
realCount = count
try:
global Session
session = Session()
rec = TblFoo(counter=count,
dateTime=datetime.today().isoformat())
session.add(rec)
session.commit()
count += 1
except exc.InternalError as e:
print('{} Exception: {}'.format(count, e))
global engine
engine.dispose()
engine = create_engine('mysql+pymysql://name:pwd@127.0.0.1',
pool_pre_ping=True, pool_recycle=1)
Session = sessionmaker(bind=engine)
continue
except Exception as e2:
print('Error', e2)
raise
finally:
session.close()
if realCount != count:
sleep(realCount*5)
Handle Error: <sqlalchemy.engine.base.ExceptionContextImpl object at 0x1076b6fd0>
Some other error: (1046, 'No database selected')
2 Exception: (pymysql.err.InternalError) (1046, 'No database selected') [SQL: 'INSERT INTO `Foo` (counter, `dateTime`) VALUES (%(counter)s, %(dateTime)s)'] [parameters: {'counter': 2, 'dateTime': '2019-08-28T15:09:47.498157'}] (Background on this error at: http://sqlalche.me/e/2j85)
2 Exception: (pymysql.err.InternalError) (1046, 'No database selected') [SQL: 'INSERT INTO `Foo` (counter, `dateTime`) VALUES (%(counter)s, %(dateTime)s)'] [parameters: {'counter': 2, 'dateTime': '2019-08-28T15:09:47.503714'}] (Background on this error at: http://sqlalche.me/e/2j85)
def createFooRecords():
计数=1
当计数小于1000000时:
realCount=count
尝试:
全球会议
会话=会话()
rec=TblFoo(计数器=计数,
dateTime=dateTime.today().isoformat())
会话.添加(rec)
session.commit()
计数+=1
除exc.InternalError为e外:
打印(“{}异常:{}”。格式(计数,e))
全球引擎
处理引擎
引擎=创建引擎('mysql+pymysql://name:pwd@127.0.0.1',
池\u pre\u ping=True,池\u recycle=1)
会话=会话生成器(绑定=引擎)
持续
例外情况除外,如e2:
打印('错误',e2)
提升
最后:
session.close()
如果realCount!=计数:
睡眠(realCount*5)
处理错误:
其他一些错误:(1046,“未选择数据库”)
2异常:(pymysql.err.InternalError)(1046,“未选择数据库”)[SQL:“插入到`Foo`(计数器,`dateTime`)值(%(计数器)s,%%(dateTime)s)][参数:{'counter':2,'dateTime':'2019-08-28815:09:47.498157'”(此错误的背景信息位于:http://sqlalche.me/e/2j85)
2异常:(pymysql.err.InternalError)(1046,“未选择数据库”)[SQL:“插入到`Foo`(计数器,`dateTime`)值(%(计数器)s,%%(dateTime)s)][参数:{'counter':2,'dateTime':'2019-08-28815:09:47.503714'”(此错误的背景信息位于:http://sqlalche.me/e/2j85)
。。。当“count”永远不递增时,会有无数的数据流
net,如何从陈旧的连接中恢复(最好是在签出时)。我有一个相当复杂的应用程序,它只使用ORM,并且有许多数据库(阅读:
def createFooRecords():
count = 1
while count < 1000000:
realCount = count
try:
global Session
session = Session()
rec = TblFoo(counter=count,
dateTime=datetime.today().isoformat())
session.add(rec)
session.commit()
count += 1
except exc.InternalError as e:
print('{} Exception: {}'.format(count, e))
global engine
engine.dispose()
engine = create_engine('mysql+pymysql://name:pwd@127.0.0.1',
pool_pre_ping=True, pool_recycle=1)
Session = sessionmaker(bind=engine)
continue
except Exception as e2:
print('Error', e2)
raise
finally:
session.close()
if realCount != count:
sleep(realCount*5)
Handle Error: <sqlalchemy.engine.base.ExceptionContextImpl object at 0x1076b6fd0>
Some other error: (1046, 'No database selected')
2 Exception: (pymysql.err.InternalError) (1046, 'No database selected') [SQL: 'INSERT INTO `Foo` (counter, `dateTime`) VALUES (%(counter)s, %(dateTime)s)'] [parameters: {'counter': 2, 'dateTime': '2019-08-28T15:09:47.498157'}] (Background on this error at: http://sqlalche.me/e/2j85)
2 Exception: (pymysql.err.InternalError) (1046, 'No database selected') [SQL: 'INSERT INTO `Foo` (counter, `dateTime`) VALUES (%(counter)s, %(dateTime)s)'] [parameters: {'counter': 2, 'dateTime': '2019-08-28T15:09:47.503714'}] (Background on this error at: http://sqlalche.me/e/2j85)