1

メイン DB があり、他のデータがセカンダリ データベースに格納されるアプリケーションを作成しています。セカンダリ データベースは、「プラグイン」アプローチに従います。SQL Server を使用しています。

アプリケーションを簡単にインストールすると、mainDB だけが作成されますが、オプションとして、より多くの「プラグイン」を有効にすることができ、プラグインごとに新しいデータベースが作成されます。

この選択をした理由は、既存のレガシー システムを使用する必要があり、これがプラグイン システムを実装する上で最も賢明なことだと考えたからです。

MainDB とプラグイン DB はまったく同じスキーマを持っています (基本的に、プラグイン DB にはいくつかの「特別なコンテンツ」があり、一種のテンプレートとして使用できるいくつかの重要なデータがあります。たとえば、アプリケーションでレター テンプレートを考えてください)。プラグイン DB は読み取り専用モードで使用されるため、「コンテンツのリポジトリ」です。「スマート」な点は、メイン アプリケーションを「プラグイン ライター」も使用できることです。彼らはコンテンツを挿入する DB を作成し、データベースのバックアップを作成することで潜在的なプラグインを作成します (これが、すべての DB が同じスキーマ)。

完全な PlugIn DB が破棄され、同じ名前の新しい DB が作成されるたびに、コンテンツのアップグレードが利用可能であるため、これらのプラグイン DB はインターネットからダウンロードされます。これは単純化のためであり、この DB のサイズは一般に小さいためです。

これでうまくいきましたが、プラグイン DB をメイン アプリケーション DB の「サブ DB」に強制できるように、DB を一種のツリー構造で編成することをお勧めします。

回避策として、次のような命名規則を使用することを考えています。

ApplicationDB (メインアプリケーション DB 用)

ApplicationDB_PlugIn_N (N 番目のプラグイン DB 用)

プラグイン 1 を検索すると、ApplicationDB_PlugIn_1 に接続しようとします。DB が見つからない場合、エラーが発生します。この状況は、たとえば、一部の DBA が ApplicationDB_Plugin_1 の名前を変更した場合に発生する可能性があります。

したがって、これらのプラグイン DB は実際には ApplicationDB のみに依存しているため、「サブフォルダーのトリックを実行」しようとしていました。

誰でもこれを行う方法を提案できますか? 上記で説明したこの自作プラグインのアプローチについてコメントしていただけますか?

追加情報 (バウンティ開始後):

MainDB では、すべてのプラグイン DB への接続情報を保存する予定です。基本的にはデータベース名です。複数のSQLサーバーログインを使用してMainDBにアクセスしても、舞台裏で単一のユーザー(通常は「sa」または管理者権限を持つ別のユーザー)になるようにシステムを設計したためです。

したがって、基本的に、複数のデータベースにクエリを実行する必要がある場合は、データベース名を使用してプラグインを区別します。データベース テーブルに PluginID というフィールドを明示的に作成する必要はありません。

どういうわけかそれはこのように機能します。メイン DB にプラグイン DB 名を保存します。プラグインの名前はわかっているので、すべてのプラグインからすべての GUNS を照会したい場合は、次のようにします。

select * from ApplicationDB_Plugin_1.dbo.weapons where weapon_type = 'gun'
union
select * from ApplicationDB_Plugin_2.dbo.weapons where weapon_type = 'gun'
union
select * from ApplicationDB_Plugin_3.dbo.weapons where weapon_type = 'gun'

したがって、「トリック」はプラグインを区別するためにdbnameを使用しています。今この作品ですが、私には少し「汚い」ようです。私の質問は、「想像できるより良いアプローチはありますか?」ということです。

4

3 に答える 3

6

スキーマを使用できます。

CREATE TABLE mytable (id INT)
GO

CREATE SCHEMA plugin_schema
CREATE TABLE mytable (id INT)
GO

SELECT  *
FROM    dbo.mytable -- selects from the first one

SELECT  *
FROM    plugin_schema.mytable  -- selects from the second one
于 2010-05-20T10:29:09.847 に答える
2

スキーマが同一である場合、一部のデータがプラグイン 1 からのものであり、他のデータがプラグイン 2 からのものであることがわかるように、既存のテーブルに何かを追加できますか? 将来、「クロスプラグイン クエリ」を実行する必要があるかもしれません。

于 2010-05-26T16:32:06.317 に答える
1

I can understand how you arrived at your current solution. Keeping the databases separate makes it clear which data belongs to each plugin, and keeps concerns separate.

Although it offers clarity through a simple organization, this approach has some fairly significant downsides:

  • Connecting to a different db for each plugin is not going to be face. The database server will have a run a query N times to query N plugins, since it has to run each query against a separate database for each plugin.

  • Referential integrity is not easily enforcable across several databases (if at all) so it's quite likely your data may become inconsistent.

  • reduced flexibility and "dynamism": creating a new database quite a heavy operation, and so adding a new plugin becomes quite a heavy operation.

  • Finally, dealing with schema changes will be difficult - if you have a plugin that hasn't been updated to the latest schema, then it cannot be used in this scheme since all databases are assumed to have the same structure.

I would suggest a hybrid approach: each plugin continues to maintain it's own database which can be downloaded, and loaded at runtime, but rather than keeping the application and plugins in separate databases, the plugin data and application ddata are copied to a composite database. The composite database can be built at startup, or when the set of plugins changes, or as a new plugin version becomes available. This is workable since you mention each plugin database is only read, and not updated. (Rebuilding the database can be done so that the application data in the composite database is preserved.)

When the application data and the data from the plugins are integrated into one database you avoid the problems above:

  • the database server executes just one query rather than one per plugin

  • referential integrity is enforceable since all the data is maintained in one database.

  • finally, and most importantly, in my view - managing schema changes becomes possible. If there are plugins that haven't implemented your latest schema changes, the merging process can adapt data stored using the old schema while it is copying the plugin data to the composite dataabase (which always uses the latet schema.) For example, while copying a plugin using the old schema, default values can be added for new columns, changes in structure can be accomodated, columns/rows can be deleted etc. The same "schema upgrade" code can also be given to plugin developers to allow them to upgrade their plugin schema.

The merge process could also build an "installed_plugins" table listing all the plugins that are copied to the composite database. The table contains metadata about each plugin such as date of plugin update, time added, unique plugin id etc.

So, what does the composite database look like:

  1. plugin data stored as separate tables, using a view to combine them, The view would be a union of a corresponding table from each plugin, plus the a column for the plugin id. This will work, but is not likely to be efficient.
  2. plugin data for a given table type are all stored together. Referential integrity is much easier to maintain and queries are going to be faster, since a common index can be used across all plugins.

My preference is for the second option. But with all plugin data stored together, how to know which plugin each row comes from? Again there are two options:

  1. Add an extra column to the table with the plugin id/name. The advantage is that it's fast. The disadvantage is that it changes the base schema.
  2. For each table, have a companion table that maps a row ID to the plugin ID where the data was sourced from. This will be a little slower to query, but keeps the schema of your core data tables free from changes.

For simplicity, my preference would be for 1, adding an ID column. Since the tables in the composite database are built by a script or program, either scheme is simple to implement, and so it's mostly about preference or performance needs or whether it's important that the merge database uses the same schema for the core data tables as the original application database.

I feel that merging the data together is the right approach, for less pain, easier maintainance, flexibility and greater performance. But if you still have strong motives for keeping the data in separate tables, then at least keep them in the same database, and use either table name prefix, or better, schema names to keep the plugin data namespaces separate.

Good luck, which ever way you choose!

于 2010-05-28T17:58:07.553 に答える