1

Rails 3.2 のマルチテナント サブドメイン ベースのアプリを PostgreSQL のスキーマに移行しようとしています (各アカウントは独自のスキーマを取得しています。現在、すべてのアカウントが同じテーブルを使用しています)。

だから、私は私がする必要があると考えています:

  1. 新しい DB を作成する
  2. 各アカウント (その ID) とその下のテーブルのスキーマを作成します
  3. 各アカウントに属するすべてのデータを取得し、そのアカウントのスキーマの下にある新しい DB に挿入します

その音は正しいですか?もしそうなら、それを行う良い方法は何ですか?ActiveRecord を使用してデータを取り出し、それを新しい DB に挿入する Ruby スクリプトを作成する必要がありますか? それとも、Postgres はそのようなことを行うための優れたツールを提供していますか?

編集:

Craig が勧めたように、既存の DB にスキーマを作成しました。次に、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
4

1 に答える 1

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、おそらく外部制御スクリプトから行うので、各顧客の作業が個別に行われ、コミットされ、最後から2番目の顧客の変換が失敗した場合に最初からやり直す必要がなくなります。

ボーナスクレイジーポイントについては、メインの顧客スキーマのテーブルにトリガーを定義して、すでに移行された顧客への変更を新しいスキーマのデータのコピーに複製することも可能です。これにより、顧客は移行中にシステムを使い続けることができます。移行が大きすぎてダウンタイムなしで実行できない場合を除いて、これは避けたいと思います。テストするのは悪夢であり、xの移行中に顧客IDxによるアクセスでエラーをスローするトリガーが必要になるためです ■データは実際には進行中であるため、完全に透過的ではありません。

顧客ごとに異なるログインユーザーを使用している場合(強く推奨)、関数は次のこともできます。

  • REVOKEからのスキーマの権利public
  • GRANTスキーマに対する制限付きの権限は、スキーマを使用するユーザーまたはロールに限定されます
  • REVOKE作成された各テーブルからの公開権
  • GRANTユーザーとロールに対する各テーブルの必要な制限付き権限
  • GRANTそれらのテーブルで使用されるすべてのシーケンス。SERIALこれは、シーケンスが疑似列によって作成されている場合でも必要です。

そうすれば、すべての権限に一貫性があり、後でアクセスして変更する必要がありません。Webアプリはスーパーユーザーとしてログインしないでください。

于 2012-08-07T23:33:15.870 に答える