我有一个基于Rails 3.2多租户子域的应用程序,我正在尝试迁移到PostgreSQL的架构(每个帐户都有自己的架构 - 现在所有帐户都使用相同的表格。)
所以,我想我需要:
这听起来不对吗?如果是这样,那么这样做的好方法是什么?我应该编写一个使用ActiveRecord的ruby脚本,提取数据,然后将它(非常低效,但应该完成工作)插入到新数据库中?或者Postgres是否提供了做这种事情的好工具?
编辑:
正如Craig建议的那样,我在现有数据库中创建了模式。然后我在Rake任务中循环遍历所有帐户,用以下内容复制数据:
Account.all.each do |account|
PgTools.set_search_path account.id, false
sql = %{INSERT INTO tags SELECT DISTINCT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."tagger_id" = #{admin.id} AND "taggings"."tagger_type" = 'User'}
ActiveRecord::Base.connection.execute sql
#more such commands
end
答案 0 :(得分:3)
我会亲自使用SQL进行转换。
在与当前数据库相同的数据库中创建新模式以便于迁移,因为您无法使用PostgreSQL轻松地跨数据库进行查询。
使用适当的INSERT INTO ... SELECT
查询迁移数据。要在不必禁用任何外键的情况下执行此操作,您应该构建数据的依赖关系图。将数据复制到首先依赖于任何内容的表中,然后再依赖于它们的表,依此类推。
您需要为每个客户架构重复此操作,因此请考虑创建一个使用EXECUTE ...
动态SQL的PL / PgSQL函数:
通过循环遍历硬编码的表名数组,以正确的顺序复制数据,执行:
EXECUTE `'INSERT INTO '||quote_ident(newschema)||'.'||quote_ident(tablename)||' SELECT * FROM oldschema.'||quote_ident(tablename)||' WHERE customer_id = '||quote_literal(customer_id)'||;'
其中newschema
,tablename
和customer_id
是PL / PgSQL变量。
然后,您可以从SQL调用该函数。虽然你可以只做select convert_customer(c.id) FROM customer GROUP BY c.id
,但我可能只是通过一个外部控制脚本来完成它,这样每个客户的工作都可以完成并单独提交,如果倒数第二个客户转换,则无需再从头开始失败。
对于奖励疯狂点,甚至可以在主要客户架构的表上定义触发器,这些触发器将已迁移客户的更改复制到新架构中的数据副本,以便他们可以在迁移期间继续使用系统。我会避免这种情况,除非迁移太大而没有停机时间,因为测试是一个噩梦,你仍然需要触发器来引发客户ID x 虽然 x 的数据迁移实际上正在进行中,因此它不会完全透明。
如果您为不同的客户使用不同的登录用户(强烈推荐),您的功能还可以:
REVOKE
的架构的public
权利
GRANT
模式对用户或角色的有限权利REVOKE
来自每个创建的表的公开权GRANT
每个表对用户和角色的所需有限权利GRANT
关于这些表使用的任何序列。即使序列是由SERIAL
伪列创建的,也需要这样做。这样,您的所有权限都是一致的,您无需在以后更改它们。请记住,您的网络应用从不以超级用户身份登录。