postgresql SQLAlchemy:了解事务中的Select语句

icomxhvb  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(1)|浏览(156)

我试图理解SQLAlchemy Sessions的行为以及它们与PostgreSQL事务的关系,因为它们的行为似乎并不完全相同。我创建了一个简单的程序来插入、更新和随后更新一行:

engine = sa.create_engine(f"postgresql+psycopg2://{pg_user}:@{pg_host}:{pg_port}/{pg_db}", echo=True)
Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)

Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine, expire_on_commit=True)
session = Session()

# Add a user
u1 = User(id=1, name="u1")
session.add(u1)
session.commit()

# Modify user's name
session.query(User).filter_by(id=1).update({"name": "u2"})
session.commit()

# Get user's name
user = session.query(User).filter_by(id=1).one()
print(user.name) # prints "u2" as expected

但是,如果我现在删除modification和select之间的session.commit()语句,我会得到一个意想不到的结果:

# ...

# Modify user's name
session.query(User).filter_by(id=1).update({"name": "u2"})

# Get user's name
user = session.query(User).filter_by(id=1).one()
print(user.name) # prints "u1" -- NOT expected!

这可能是因为会话正在查询数据库,而数据库中的用户名尚未更新(因为事务尚未提交)。但是,我认为,因为我使用相同的session对象来查询用户,所以它应该能够识别事务中User对象上发生的更改。
我不明白什么?

1szpjjfi

1szpjjfi1#

PostgreSQL使用“Read Committed”隔离级别。这意味着正在执行的每个查询都会看到较早提交的数据。
因此,当您在没有“session.commit()"的情况下进行更改时,这些更改不是在数据库中进行的,因此查询看不到这些更改。提交更改后,更改将在数据库中进行,同一会话中即将进行的查询将看到更新的数据。
为了避免在每次查询后都出现“session.commit()”,可以将“autocommit”设置为true。

相关问题