我正在创建一个应用程序,其中有主DB,其他数据存储在辅助数据库中。辅助数据库遵循“插件”方法。我使用SQL Server。
应用程序的简单安装只有mainDB,而作为选项,可以激活更多的“插件”,每个插件都会有一个新的数据库。
现在为什么我做出这个选择是因为我必须使用现有的遗留系统,这是我能想到的最聪明的事情来实现插件系统。
MainDB和插件数据库具有完全相同的模式(基本上插件数据库有一些“特殊内容”,一些可以用作模板的重要数据 - 例如在应用程序中考虑信件模板)。插件DB在只读模式中使用,它们是“内容存储库”。 “聪明”的事情是主要的应用程序也可以被“插件编写者”使用,他们只是编写一个数据库插入内容,并通过备份数据库,他们创建了一个潜在的插件(这就是为什么所有的数据库都有相同的模式)。
这些插件数据库是从互联网上下载的,因为有可用的内容升级,每次销毁完整的PlugIn数据库并且创建一个具有相同名称的新插件数据库。这是为了简单起见,甚至因为这个DB的大小通常很小。
现在这个工作了,无论如何我更喜欢用一种树结构组织DB,这样我就可以强制插件DB成为主应用程序DB的“子DB”。
作为一种解决方法,我正在考虑使用命名规则,例如:
ApplicationDB(用于主应用程序DB)
ApplicationDB_PlugIn_N(对于第N个插件DB)
当我搜索插件1时,我尝试连接到ApplicationDB_PlugIn_1,如果我没有找到数据库,则会引发错误。例如,如果som DBA重命名为ApplicationDB_Plugin_1,就会发生这种情况。
因为那些插件DB实际上只依赖于ApplicationDB,所以我试图“执行子文件夹技巧”。
有人可以建议一种方法吗?您能评论一下我上面描述的这种自制的插件方法吗?
添加信息(开始播放后):
在MainDB中,我计划将连接信息存储到所有插件DB中。基本上它是数据库名称,因为我以一种方式设计了系统,即使我使用多个sql server登录访问MainDB,在幕后还有一个用户(通常是“sa”或具有管理员权限的其他用户)。 p>
所以基本上如果我需要查询多个数据库,我将使用数据库名来区分插件,我不需要在数据库表中显式创建名为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来区分插件。现在这项工作,但对我来说似乎有点“肮脏”。我的问题是“你有更好的方法吗?”
答案 0 :(得分: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
答案 1 :(得分:2)
如果模式相同,您可以在现有表中添加一些内容,这样您就可以知道某些数据来自插件1而其他数据来自插件2吗?您可能会发现将来需要进行“交叉插件查询”?
答案 2 :(得分:1)
我能理解你是如何达到目前的解决方案的。保持数据库分离可以清楚地知道哪些数据属于每个插件,并将问题分开。
虽然它通过一个简单的组织提供了清晰度,但这种方法有一些相当重要的缺点:
连接到每个插件的不同数据库不会是面子。数据库服务器将运行查询N次以查询N个插件,因为它必须针对每个插件针对单独的数据库运行每个查询。
参考完整性不容易在多个数据库中执行(如果有的话),因此您的数据很可能会变得不一致。
降低了灵活性和“动态性”:创建一个新的数据库非常繁重的操作,因此添加一个新的插件变得非常繁重。
最后,处理架构更改将很困难 - 如果您有一个尚未更新到最新架构的插件,那么它不能在此方案中使用,因为假定所有数据库具有相同的结构
我建议采用混合方法:每个插件继续维护自己的数据库,可以下载并在运行时加载,但不是将应用程序和插件保存在单独的数据库中,而是将插件数据和应用程序ddata复制到复合数据库。复合数据库可以在启动时构建,也可以在插件集更改时构建,或者在新的插件版本可用时构建。这是可行的,因为你提到每个插件数据库只被读取,而不是更新。 (可以重建数据库,以便保留复合数据库中的应用程序数据。)
当应用程序数据和插件中的数据集成到一个数据库中时,您可以避免上述问题:
数据库服务器只执行一个查询,而不是每个插件执行一次
参与完整性是可执行的,因为所有数据都保存在一个数据库中。
最后,最重要的是,在我看来 - 管理架构变更成为可能。如果有插件未实现最新的架构更改,则合并过程可以调整使用旧架构存储的数据,同时将插件数据复制到复合数据库(始终使用latet架构)。例如,在复制时使用旧模式的插件,可以为新列添加默认值,可以容纳结构中的更改,可以删除列/行等。也可以向插件开发人员提供相同的“模式升级”代码以允许他们升级他们的插件架构。
合并过程还可以构建一个“installed_plugins”表,其中列出了复制到复合数据库的所有插件。该表包含有关每个插件的元数据,例如插件更新日期,添加时间,唯一插件ID等。
那么,复合数据库是什么样的:
我的偏好是第二种选择。但是将所有插件数据存储在一起,如何知道每行插件来自哪一个?同样有两种选择:
为简单起见,我的首选是1,添加ID列。由于复合数据库中的表是由脚本或程序构建的,因此任何一种方案都很容易实现,因此主要是关于首选项或性能需求,或者合并数据库是否使用与核心数据表相同的模式非常重要。原始申请数据库。
我认为将数据合并在一起是正确的方法,可以减少痛苦,减轻维护,提高灵活性和提高性能。但是,如果您仍然有强大的动机将数据保存在单独的表中,那么至少将它们保存在同一个数据库中,并使用表名前缀或更好的模式名称来保持插件数据命名空间分开。
祝你好运,你选择哪种方式!