Row Level Security
公式ドキュメント
マルチテナントトの兼ね合い
テナントデータどうパーティションするか
用語
テナントごとに個別のデータベースインスタンスを使用
インフラストラクチャコストが高くなる
テナントのセットアップがより複雑になる
各テナントに、新しいデータベースインスタンスを作成および管理する必要がある
同じデータベースインスタンスを共有しながら、テナントごとに異なるスキーマを使用する
コストを削減できる
メンテナンスとテナントのセットアップはかなり複雑になる可能性がある
スキーマを分離
マイグレーションがスケールしない
各テーブルまたはビューには、データのフィルターに使用するパーティション分割キー (通常はテナント ID) が含める
-> Row Level Securityで安全にフィルタリングする
code:SQL
CREATE TABLE invoice (
tenant_id varchar(20) NOT NULL,
invoice_uuid uuid NOT NULL PRIMARY KEY,
publisher varchar(50) NOT NULL
);
ALTER TABLE invoice ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_policy ON invoice USING (tenant_id = current_setting('app.tenant_id'));
tenant_idの指定の仕方
SELECT set_config('app.tenant_id', :tenantId, false);
SETではなくset_configなのはプレースホルダーが使えるため
userをわける必要があるか
ない気がするな...
リクエスト -> コンテキスト作成 -> tenantの特定 -> current_setting で指定
userの場合 リクエスト -> コンテキスト作成 -> tenantの特定 -> 該当ユーザーでログイン
コネクション作り直さないといけない(あるいはユーザー分事前に用意してお必要がある)
DB connection = request scopeでいいか
すべてのtenantにまたがる処理をどうするか
リクエストと非同期に処理したい場合どうするか
コネクションプール
理想
グローバルなコネクションプール
コネクションを取得後テナントに対応したユーザーに切り替え(あるいはset_config)
次善策
テナントごとにコネクションプールを用意
テナント増えてきたとき現実的ではなさそう
都度接続
オーバーヘッドが大きい
小規模ならばまぁええやろ
Prisma2との思想にあわない