为什么在SQLAlchemy中有一个未绑定到引擎的MetaData对象是有用的?

时间:2011-08-08 14:18:48

标签: python sqlalchemy metadata

我试图理解MySQL关于MetaData对象和engine对象的行为。 This SO-AnswerMetaData描述为

  

表定义的集合

engine

  

特定数据库的方言和连接细节

到目前为止一切顺利。但什么时候将这两者分开是有用的?表定义是否未链接到特定数据库?

2 个答案:

答案 0 :(得分:10)

SQLAlchemy 0.1没有“元数据”对象 - Engine直接绑定到每个Table。这个想法变得非常快,部分是因为人们想要在连接之前声明他们的Table对象,并且出现了“绑定元数据”。然后,发生了长时间的大规模混乱。人们处于超级艰难的习惯(因为我告诉他们这样做),他们说的是:

table.insert().execute()

result = table.select().execute()

即,没有交易,每次都使用新连接。然后我们会说,“哦,你应该使用交易,你应该更有效率地进行交易”,然后我们基本上告诉他们他们必须重写他们的应用程序,而“sqlalchemy有太多方法”模因像气球一样爆炸。

与此同时,Pylons和其他早期的WSGI框架正在努力让多个“应用程序”同时运行 - 在某些情况下,不同的“用户”会在不同的数据库中拥有自己的一组表,有点像。更常见的是水平扩展方法,其中相同的表位于许多数据库中。我这里有一个应用程序,内置一个“复制”系统,其中记录定期从“主”数据库复制到“历史”数据库,并且那里的表元数据也是共享的。

关键在于所有这些用例,用户会来到SQLA,他们对事物的理解始于“绑定元数据”。各地的博客和教程都使用它。这些用户中的很大一部分需要突破该系统,并且完全混淆了整个“其他方式”的工作方式。所以很明显,“绑定元数据”系统只是一个默认的过于严格。理想情况下,我希望我从来没有实现它,我自己从不使用它。这就是为什么现在将文档推送到一个部分,只是浏览文档的新用户,他们的性质给邮件列表增加了巨大的支持负担,但是找不到它并且不会混淆。该部分本身有很多项目符号,可以准确地解释何时以及为何混淆。我假设你在http://www.sqlalchemy.org/docs/core/schema.html#binding-metadata-to-an-engine-or-connection读到它。

答案 1 :(得分:5)

实际上,表定义不是链接到特定数据库。 sqlalchemy元数据对象和所有附加对象(表,列,索引等)定义完全抽象的模式,而不引用任何特定的数据库。引擎基本上是三件事:连接信息,方言和连接池。方言是这里的重要部分,它定义了如何连接到特定的数据库,但更重要的是关于你的问题,它还定义了如何将sqla的抽象模式对象(元数据等)转换为sql命令特定于那个数据库和驱动程序

这种分离有许多不同的用途:

  • 应用程序可以在模块级别定义他们的架构,在导入模块时创建表格和元数据......但是在定义引擎实际启动并运行之前不需要定义引擎(因为知道完整的连接URL和放大器) ;方言通常需要先读取配置文件或获取用户输入)。

  • 您可以将多个引擎的情况绑定到同一组元数据,例如webapp,其中每个用户/密码使用自己的凭据连接到数据库(不是说这是有效的,但有时需要安全目的)。由于元数据是一个全局对象,因此在这种情况下将它绑定到特定引擎是没有意义的。

  • 这种情况很少见,但您也可以使用相反的情况,单个引擎有多个元数据实例。当多个子组件共享同一个数据库但使用不同的表名时,可能会发生这种情况。此外,当尝试将应用程序在一个元数据实例中的当前架构与从服务器反射的另一个元数据实例(例如用于架构迁移的目的)进行比较时,可能会发生这种情况。这不会严格阻止您将每个绑定到引擎,但确实有助于演示如何有效地使用多个元数据或引擎实例。

可能还有一些我现在无法想到的用例,但是这应该让你大致了解为什么它们在概念上彼此分离。