postgresql 在回滚无效事务之前无法重新连接,FastApi

yeotifhr  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(132)

我有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]

hyrbngr7

hyrbngr71#

该错误是因为您启动了一个事务,但长时间没有运行查询,触发了超时。这在PostgreSQL服务器中配置。
https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT
除非您以某种方式与服务器交互-通常是通过运行查询--否则您不会看到这一点。
解决方案:不要打开一个事务并“坐在上面”,用你想要的第一个语句打开它。

相关问题