186

在对我的一个问题发表评论之后,我正在考虑使用一个具有 X 模式的数据库是否更好,反之亦然。

我正在开发一个网络应用程序,当人们注册时,我创建(实际上)一个数据库(不,它不是一个社交网络:每个人都必须有权访问自己的数据,并且永远不会看到其他用户的数据)。这就是我在以前版本的应用程序中使用的方式(仍在 MySQL 上运行):通过 Plesk API,对于每次注册,我都会:

  1. 创建具有有限权限的数据库用户;
  2. 创建一个只能由之前创建的用户和超级用户访问的数据库(用于维护)
  3. 填充数据库

现在,我需要对 PostgreSQL 做同样的事情(项目正在变得成熟,而 MySQL 并不能满足所有需求)。我需要让所有数据库/模式备份独立:pg_dump两种方式都可以完美运行,对于可以配置为仅访问一个模式或一个数据库的用户也是如此。

所以,假设你是比我更有经验的 PostgreSQL 用户,你认为什么是适合我情况的最佳解决方案,为什么?使用 $x 数据库而不是 $x 模式会有性能差异吗?未来有什么解决方案会更好地维护(可靠性)?我所有的数据库/模式将始终具有相同的结构!

对于备份问题(使用 pg_dump),使用一个数据库和多个模式可能会更好,一次转储所有模式:恢复将非常简单,将主转储加载到开发机器中,然后仅转储和恢复所需的模式:那里是一个额外的步骤,但是转储所有模式似乎比一个一个地转储它们更快。

2012 年更新

好吧,在过去的两年里,应用程序的结构和设计发生了很大的变化。我仍在使用“一个具有多个模式的数据库” - 方法,但是,我的应用程序的每个版本都有一个数据库:

Db myapp_01
    \_ my_customer_foo_schema
    \_ my_customer_bar_schema
Db myapp_02
    \_ my_customer_foo_schema
    \_ my_customer_bar_schema

对于备份,我定期转储每个数据库,然后将备份移动到开发服务器上。我也在使用 PITR/WAL 备份,但正如我之前所说,我不可能一次恢复所有数据库。所以它可能会在今年被解雇(在我的情况下不是最好的方法)。

从现在开始,one-db-many-schema 方法对我来说效果很好,即使应用程序结构完全改变了。我几乎忘记了:我所有的数据库/模式将始终具有相同的结构!现在,每个模式都有自己的结构,可以根据用户数据流动态变化。

4

7 回答 7

163

PostgreSQL“模式”与 MySQL“数据库”大致相同。在 PostgreSQL 安装上拥有许多数据库可能会出现问题;拥有许多模式将毫无困难。因此,您肯定希望在该数据库中使用一个数据库和多个模式。

于 2009-07-21T02:25:46.410 回答
34

当然,我会选择 one-db-many-schemas 方法。这使我可以转储所有数据库,但可以通过多种方式非常轻松地仅恢复一个:

  1. 转储数据库(所有架构),将转储加载到新数据库中,仅转储我需要的架构,然后在主数据库中恢复。
  2. 一个一个地单独转储模式(但我认为机器会以这种方式遭受更多损失 - 我期待有 500 个模式!)

否则,谷歌搜索我发现没有自动程序来复制模式(使用一个作为模板),但许多人建议这样:

  1. 创建模板模式
  2. 当需要复制时,用新名称重命名
  3. 转储它
  4. 重命名回来
  5. 恢复转储
  6. 魔术完成了。

我已经用 Python 写了两行来做到这一点;我希望他们可以帮助某人(在 2 秒内编写代码,不要在生产中使用它):

import os
import sys
import pg

# Take the new schema name from the second cmd arguments (the first is the filename)
newSchema = sys.argv[1]

# Temperary folder for the dumps
dumpFile = '/test/dumps/' + str(newSchema) + '.sql'

# Settings
db_name = 'db_name'
db_user = 'db_user'
db_pass = 'db_pass'
schema_as_template = 'schema_name'

# Connection
pgConnect = pg.connect(dbname= db_name, host='localhost', user= db_user, passwd= db_pass)

# Rename schema with the new name
pgConnect.query("ALTER SCHEMA " + schema_as_template + " RENAME TO " + str(newSchema))

# Dump it
command = 'export PGPASSWORD="' + db_pass + '" && pg_dump -U ' + db_user + ' -n ' + str(newSchema) + ' ' + db_name + ' > ' + dumpFile
os.system(command)

# Rename back with its default name
pgConnect.query("ALTER SCHEMA " + str(newSchema) + " RENAME TO " + schema_as_template)

# Restore the previous dump to create the new schema
restore = 'export PGPASSWORD="' + db_pass + '" && psql -U ' + db_user + ' -d ' + db_name + ' < ' + dumpFile
os.system(restore)

# Want to delete the dump file?
os.remove(dumpFile)

# Close connection
pgConnect.close()
于 2009-07-21T06:21:05.893 回答
18

我会说,使用多个数据库和多个模式:)

PostgreSQL 中的模式很像 Oracle 中的包,以防你熟悉它们。数据库旨在区分整个数据集,而模式更像是数据实体。

例如,您可以使用“UserManagement”、“LongTermStorage”等模式为整个应用程序创建一个数据库。“UserManagement”将包含“User”表,以及用户管理所需的所有存储过程、触发器、序列等。

数据库是整个程序,模式是组件。

于 2009-07-20T14:09:09.100 回答
16

由于这一系列原因,我建议不要接受接受的答案 -多个数据库而不是多个模式:

  1. 如果您正在运行微服务,您希望强制无法在您的“模式”之间加入,因此数据不会纠缠在一起,开发人员最终不会加入其他微服务的模式,并想知道为什么当其他团队不再更改他们的东西时作品。
  2. 如果您的负载需要,您稍后可以轻松迁移到单独的数据库机器。
  3. 如果您需要设置高可用性和/或复制,最好让独立的数据库彼此完全独立。与整个数据库相比,您不能仅复制一个模式。
于 2021-01-11T23:37:27.133 回答
7

在 PostgreSQL 上下文中,我建议使用一个具有多个模式的数据库,因为您可以(例如)跨模式使用 UNION ALL,但不能跨数据库。出于这个原因,一个数据库实际上与另一个数据库完全隔离,而模式与同一数据库中的其他模式并不隔离。

如果您 - 出于某种原因 - 将来必须跨模式整合数据,那么在多个模式上执行此操作将很容易。对于多个数据库,您将需要多个数据库连接,并通过应用程序逻辑“手动”收集和合并来自每个数据库的数据。

后者在某些情况下具有优势,但对于主要部分,我认为一个数据库多模式方法更有用。

于 2016-08-04T17:38:25.490 回答
5

许多模式应该比许多数据库更轻量级,尽管我找不到证实这一点的参考。

但是,如果您真的想将事情分开(而不是重构 Web 应用程序以便将“客户”列添加到您的表中),您可能仍然希望使用单独的数据库:我断言您可以更轻松地恢复以这种方式访问​​特定客户的数据库 - 不会打扰其他客户。

于 2009-07-20T20:42:02.517 回答
0

使用具有多个模式的单个数据库是在 postgres 数据库中练习的好方法,因为:

  1. postgres 中的数据库之间没有任何数据共享。
  2. 到服务器的任何给定连接都只能访问单个数据库中的数据,即连接请求中指定的数据。

使用多个模式:

  1. 允许多个用户使用一个数据库而不互相干扰。
  2. 将数据库对象组织成逻辑组以使其更易于管理。
  3. 第三方应用程序可以放入单独的模式中,因此它们不会与其他对象的名称发生冲突。
于 2021-03-26T07:02:47.260 回答