SQLAlchemy:创建与重用会话 [英] SQLAlchemy: Creating vs. Reusing a Session

查看:29
本文介绍了SQLAlchemy:创建与重用会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是一个简单的问题:SQLAlchemy 谈论调用sessionmaker() 一次,但每次需要与数据库对话时都会调用生成的 Session() 类.对我来说,这意味着第二个我会做我的第一个 session.add(x) 或类似的东西,我会先做

Just a quick question: SQLAlchemy talks about calling sessionmaker() once but calling the resulting Session() class each time you need to talk to your DB. For me that means the second I would do my first session.add(x) or something similar, I would first do

from project import Session
session = Session()

到目前为止,我所做的是在我的模型中调用 session = Session() 一次,然后始终在我的应用程序中的任何位置导入相同的会话.由于这是一个 Web 应用程序,因此通常意味着相同(当执行一个视图时).

What I did until now was to make the call session = Session() in my model once and then always import the same session anywhere in my application. Since this is a web-applications this would usually mean the same (as one view is executed).

但是区别在哪里呢?一直使用一个会话与将它用于我的数据库内容直到我的功能完成然后在下次我想与我的数据库交谈时创建一个新会话的缺点是什么?

But where is the difference? What is the disadvantage of using one session all the time against using it for my database stuff until my function is done and then creating a new one the next time I want to talk to my DB?

我知道如果我使用多个线程,每个线程都应该有自己的会话.但是使用 scoped_session(),我已经确定这个问题不存在,是吗?

I get that if I use multiple threads, each one should get their own session. But using scoped_session(), I already make sure that problem doesn't exist, do I?

请说明我的假设是否有误.

Please clarify if any of my assumptions are wrong.

推荐答案

sessionmaker() 是一个工厂,它鼓励放置配置选项以创建新的 Session 对象只在一处.它是可选的,因为您可以在需要新的 Session 的任何时候轻松调用 Session(bind=engine, expire_on_commit=False),除了它冗长和冗余,我想阻止小规模帮手"的扩散,他们每个人都以一些新的、更令人困惑的方式处理这种冗余问题.

sessionmaker() is a factory, it's there to encourage placing configuration options for creating new Session objects in just one place. It is optional, in that you could just as easily call Session(bind=engine, expire_on_commit=False) anytime you needed a new Session, except that its verbose and redundant, and I wanted to stop the proliferation of small-scale "helpers" that each approached the issue of this redundancy in some new and more confusing way.

所以 sessionmaker() 只是一个工具,可以帮助您在需要时创建 Session 对象.

So sessionmaker() is just a tool to help you create Session objects when you need them.

下一部分.我认为问题是,在不同的点上创建一个新的 Session() 与一直使用一个有什么区别.答案,不是很多.Session 是您放入其中的所有对象的容器,然后它还跟踪打开的事务.在您调用 rollback()commit() 的那一刻,事务结束,并且 Session 没有连接到数据库,直到它被要求再次发出 SQL.它保存到映射对象的链接是弱引用,前提是对象没有挂起的更改,因此即使在这方面 Session 也会在您的应用程序丢失所有内容时将自身清空回全新状态对映射对象的引用.如果您将其保留为默认的 "expire_on_commit" 设置,那么所有对象都会在提交后过期.如果那个 Session 挂了 5 到 20 分钟,并且下次使用它时数据库中的各种事情都发生了变化,那么下次访问这些对象时它甚至会加载所有全新的状态尽管他们已经在记忆中坐了二十分钟.

Next part. I think the question is, what's the difference between making a new Session() at various points versus just using one all the way through. The answer, not very much. Session is a container for all the objects you put into it, and then it also keeps track of an open transaction. At the moment you call rollback() or commit(), the transaction is over, and the Session has no connection to the database until it is called upon to emit SQL again. The links it holds to your mapped objects are weak referencing, provided the objects are clean of pending changes, so even in that regard the Session will empty itself out back to a brand new state when your application loses all references to mapped objects. If you leave it with its default "expire_on_commit" setting, then all the objects are expired after a commit. If that Session hangs around for five or twenty minutes, and all kinds of things have changed in the database the next time you use it, it will load all brand new state the next time you access those objects even though they've been sitting in memory for twenty minutes.

在 Web 应用程序中,我们通常会说,嘿,为什么不在每个请求上创建一个全新的 Session,而不是一遍又一遍地使用相同的.这种做法确保新请求开始时干净".如果前一个请求中的某些对象还没有被垃圾回收,并且如果您关闭了 "expire_on_commit",则前一个请求中的某些状态可能仍然存在,并且该状态可能甚至很老.如果您小心地将 expire_on_commit 保持打开状态并在请求结束时明确调用 commit()rollback() ,那么就可以了,但是如果你从一个全新的 Session 开始,那么你就没有任何问题了.因此,使用新的 Session 开始每个请求的想法实际上只是确保您重新开始的最简单方法,并使 expire_on_commit 的使用几乎是可选的,因为对于在一系列操作的中间调用 commit() 的操作,此标志可能会产生大量额外的 SQL.不确定这是否能回答您的问题.

In web applications, we usually say, hey why don't you make a brand new Session on each request, rather than using the same one over and over again. This practice ensures that the new request begins "clean". If some objects from the previous request haven't been garbage collected yet, and if maybe you've turned off "expire_on_commit", maybe some state from the previous request is still hanging around, and that state might even be pretty old. If you're careful to leave expire_on_commit turned on and to definitely call commit() or rollback() at request end, then it's fine, but if you start with a brand new Session, then there's not even any question that you're starting clean. So the idea to start each request with a new Session is really just the simplest way to make sure you're starting fresh, and to make the usage of expire_on_commit pretty much optional, as this flag can incur a lot of extra SQL for an operation that calls commit() in the middle of a series of operations. Not sure if this answers your question.

下一轮是你提到的线程.如果您的应用是多线程的,我们建议确保使用中的 Session 是本地的......某物.scoped_session() 默认使其成为当前线程的本地.在 Web 应用程序中,本地的请求实际上更好.Flask-SQLAlchemy 实际上向 scoped_session() 发送了一个自定义的范围函数",以便您获得一个请求范围的会话.普通的 Pyramid 应用程序将 Session 粘贴到请求"注册表中.使用此类方案时,在请求开始时创建新会话"的想法仍然是保持事情简单的最直接方式.

The next round is what you mention about threading. If your app is multithreaded, we recommend making sure the Session in use is local to...something. scoped_session() by default makes it local to the current thread. In a web app, local to the request is in fact even better. Flask-SQLAlchemy actually sends a custom "scope function" to scoped_session() so that you get a request-scoped session. The average Pyramid application sticks the Session into the "request" registry. When using schemes like these, the "create new Session on request start" idea continues to look like the most straightforward way to keep things straight.

这篇关于SQLAlchemy:创建与重用会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆