マルチテナントMySQLデータベースを設計する方法
複数の企業のデータをホストするデータベースを設計する必要があるとしましょう。次に、セキュリティと管理の目的で、さまざまな会社のデータが適切に分離されていることを確認する必要がありますが、10のサーバーで10の会社のデータをホストするために10のmysqlプロセスを開始したくありません。 mysqlデータベースでこれを行うための最良の方法は何ですか。
マルチテナントデータベースにはいくつかのアプローチがあります。議論のために、それらは通常3つのカテゴリーに分けられます。
- テナントごとに1つのデータベース。
- 共有データベース、テナントごとに1つのスキーマ。
- 共有データベース、共有スキーマ。テナント識別子(テナントキー)は、すべての行を適切なテナントに関連付けます。
MSDNには、 各設計の長所と短所 、および 実装の例 に関する優れた記事があります。
参考までに、これは 2番目の記事の元のリンク です。
簡単な方法は次のとおりです。共有テーブルごとに、SEGMENT_IDという列を追加します。各顧客に適切なSEGMENT_IDを割り当てました。次に、SEGMENT_IDに基づいて各顧客ベースのビューを作成します。これらのビューは、各顧客からデータを分離し続けます。この方法では、情報の共有が可能で、運用と開発の両方で簡単にできます(ストアドプロシージャも共有できます)。
単一のMySQLインスタンスで1つのMySQLデータベースを実行するとします。何が誰のものであるかを区別する方法はいくつかあります。 (少なくとも私にとっては)最も明白な選択は、次のような複合主キーを作成することです。
CREATE TABLE some_table (
id int unsigned not null auto_increment,
companyId int unsigned not null,
..
..
..,
primary key(id, company_id)
) engine = innodb;
次に、主キーのcompanyId部分を変更することにより、会社を区別します。これにより、すべての会社のすべてのデータを同じテーブル/データベースに含めることができ、アプリケーションレベルで、どの会社をどのcompanyIdに関連付けるかを制御し、特定の会社について表示するデータを決定できます。
これがあなたが探していたものではなかった場合-あなたの質問を誤解したことをお詫びします。
MySQLでは、すべてのテナントに対して単一のデータベースを使用することを好みます。データへのアクセスを制限するには、そのテナントに属する行のみを表示するビューへのアクセスのみを持つテナントごとに個別のデータベースユーザーを使用します。
これは次の方法で実行できます。
- すべてのテーブルにtenant_id列を追加する
- トリガーを使用して、挿入時にtenant_idに現在のデータベースユーザー名を入力します
- Tenant_id = current_database_usernameである各テーブルのビューを作成します
- アプリケーションでのみビューを使用する
- テナント固有のユーザー名を使用してデータベースに接続する
私はこれをブログ投稿で完全に文書化しました: https://opensource.io/it/mysql-multi-tenant/
特定のDBユーザーを指定して、データへのアクセスが許可されている会社を示すグループにユーザーメンバーシップを与えることができます。
Companies
テーブルがあると思いますので、Companies
とMySQLUsers
または同様の何かの間に1対多の関係を作成します。
次に、すべてのクエリの条件として、CompanyID
に基づいてUserID
を照合します
会社ごとに異なる schema を作成することを検討しましたか?
ただし、達成したいことをより正確に定義する必要があります。
たとえば、ハードウェア障害によって複数の会社のデータが損なわれないようにする場合は、異なるインスタンスを作成して、それらを異なるノードで実行する必要があります。
会社Aの誰かが会社Bに属するデータを表示できないようにしたい場合は、Matthew PKの回答に従って、アプリケーションレベルでそれを行うことができます。たとえば、
ただし、セキュリティを危険にさらしてDBに対して任意のSQLを実行した人がいることを確認したい場合は、それよりも堅牢なものが必要です。
データを個別にバックアップして、月曜日に会社Cを、日曜日に会社Aを安全にバックアップし、会社Cだけを復元できるようにしたい場合も、純粋にアプリケーションベースのソリューションは役に立ちません。