我有Fast-API代码库。我收到错误
在回滚无效事务之前无法重新连接。(关于此错误的背景:https://sqlalche.me/e/14/8s2b)
我已经想明白了
psycopg2.errors.IdleInTransactionSessionTimeout
在回滚错误之前,由于事务中空闲而终止连接。回滚错误不断出现,直到我重新启动或重新生成项目。
我的代码库是:
database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session
from config import settings
engine = create_engine(settings.DATABASE_URL, connect_args={f"options": "-c timezone=" + settings.TIME_ZONE})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Session = scoped_session(SessionLocal)
db = Session()
Base = declarative_base()
我执行数据库事务的服务-
query_utils.py
from database import db
class QueryBuilder:
...... some functions to build the query ......
def bulk_upsert_execute(self):
db.get_bind().execute(text(self.query_string))
db.commit()
db.close()
另一个我使用db示例的模型-
object_保存_and_get_model.py
from database import db
class MainObjectGetModel(BaseModel):
object_name: str
@validator('object_name')
def validate_object_existence(cls, v) -> SavedObject:
result = db.query(SavedObject).filter(SavedObject.name == v).first()
if not result:
raise HTTPException(status_code=404, detail="File not found.")
return result
我试过使用- database.py-
def handle_session_rollback(func):
@wraps(func)
def wrapper(*args, **kwargs):
session = Session()
try:
result = func(*args, **kwargs)
session.commit()
return result
except Exception as e:
session.rollback()
raise
finally:
session.close()
return wrapper
query_utils.py -
from database import db, handle_session_rollback
class QueryBuilder:
...... some functions to build the query ......
@handle_session_rollback
def bulk_upsert_execute(self):
db.get_bind().execute(text(self.query_string))
db.commit()
db.close()
如果发生任何异常,它实际上会回滚。我已经检查过了,但是IdleInTransactionSessionTimeout实际上不起作用。
我想不通为什么会出现IdleInTransactionSessionTimeout。我也试过-
try:
# Perform your operations within the session
# ...
# Commit the transaction
db.commit()
except Exception as e:
# Roll back the transaction in case of an exception
db.rollback()
# Handle the exception as needed
# ...
finally:
# Close the session
db.close()
给出与handle_session_rollback相同的结果。在这种情况下,我如何处理回滚...?
[注意:我用的是PostgreSQL]
1条答案
按热度按时间hyrbngr71#
该错误是因为您启动了一个事务,但长时间没有运行查询,触发了超时。这在PostgreSQL服务器中配置。
https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT
除非您以某种方式与服务器交互-通常是通过运行查询--否则您不会看到这一点。
解决方案:不要打开一个事务并“坐在上面”,用你想要的第一个语句打开它。