English 中文(简体)
动态修补数据库
原标题:
  • 时间:2008-10-31 09:42:01
  •  标签:

请原谅我冗长的问题。我有一个设计想法,需要一些意见。这样做是个好主意吗?我应该注意哪些陷阱?有没有其他更好的类似实现?

My situation is as follows:
I am working on a rewrite of a windows forms application that connects to a SQL 2008 (earlier it was SQL 2005) server. The application is an "expert-system" for an engineering company where we store structured data about constructions. We have control of all installations of the client software, we have no external customers or users, they are all internal to the company, and they are all be trusted not to do anything malicious to the software or database.

当前设计并没有太多的表格(大约10-20个),但其中一些表格拥有数百万属于几百个建筑物的记录。目前系统的性能还可以,但随着我们推动设计的极限,它开始变得不稳定。

作为重写的一部分,我正在考虑将数据库拆分为一个主数据库和若干个“子”数据库,每个描述一个构造。每个子数据库应具有相同的设计。这应该能消除今天我们所看到的性能问题,因为存储在每个数据库中的数据量应该小于总数据量的百分之一。

我的担心是,我们现在不仅要维护一个数据库,而是将会有数百个数据库需要保持最新状态。随着公司需求的变化,系统不断演变(你知道的),虽然我们试图向前看,以减少变更数量,但变更仍将不断出现。因此,我们需要一个系统来跟踪对系统所做的所有数据库更改,以便将其应用于子数据库。更新客户端应用程序不会是问题,我们对此有很好的控制。

我正在考虑一种更改跟踪系统,其中我们将所有更改的数据库脚本存储在主数据库的表中。然后,我们可以为每个更改分配版本号,并在每个子数据库中存储当前版本号。当客户端程序连接到子数据库时,我们可以检查数据库的版本号与主数据库的当前版本号是否匹配,如果存在版本号大于子数据库版本号的修补程序,我们将运行这些修补程序并将子数据库更新为最新版本。

在我看来,这应该可以很好地工作。对系统所做的任何更改都将在提交为数据库的新版本之前进行测试和验证。然后,该更改将首次应用于用户打开数据库的时间。我想,在应用更改时,我们会以独占模式打开数据库,但只要更改不太频繁,这应该不是问题。

那么你认为呢?这个方案可行吗?你们中有人做过类似的吗?我们应该放弃这个方案,转而使用单片集成系统吗?

最佳回答

我这里有类似的情况,虽然我使用的是MySQL。每个数据库都有一个版本表,其中包含版本(仅为整数)和更改了什么的简短注释。我使用脚本来更新数据库。每个数据库更改可以在一个函数中或者有时一个更改由多个函数完成。函数在函数名称中包含版本号。脚本查找数据库中最高的版本号,并按顺序仅应用具有更高版本号的函数。

这使得更新数据库变得容易(只需添加新的更改函数),并允许我在必要时快速升级恢复的数据库(只需再次运行脚本)。

即使在进行更改测试时,这也允许进行防御性更改。如果您想让操作更加安全,当您在表格上进行大量更改时:

def change103(...):
    "Create new table."
def change104(...):
    """Transfer data from old table to new table and make
       complicated changes in the process.
    """
def change105(...):
    "Drop old table"
def change106(...):
    "Rename new table to old table"

如果在change104()中发生错误(并且引发异常),您可以简单地从新表中删除已转换的数据,修复您的更改函数并再次运行脚本。

但我不认为在客户端连接时动态更改数据库是一个好主意。有时更改可能需要一些时间。访问数据库的软件应该与数据库的模式匹配。你得在某种程度上保持它们同步。也许你可以分发一个新的软件版本,然后当客户实际开始使用这个新的软件时,你想升级数据库。但我还没有尝试过。

问题回答

你是否考虑通过构建来对大表进行分区?这样可以将表的存储跨越多个文件/物理设备进行拆分,而不需要改变你的应用程序,从而缓解一些增长痛苦。

增加主轴(更多驱动器)并执行一些DBA工作往往比修改/适应软件更便宜。

否则,我会赞同 @heikogerlach 和类似的帖子:

我如何在 SVN 中对我的 MS SQL 数据库进行版本控制?

用于跟踪数据库架构更改的机制

你如何管理开发、测试和生产中的数据库?

最好不要创建额外的数据库。一开始你可能会认为你会获得一些性能提升,但实际上你会陷入支持的噩梦中。请记住 - 什么能出错,迟早都会出错。

在单数据库中执行和优化查询更加简单。在单数据库中管理用户权限更加容易。为单个数据库创建一致的备份更加容易。

就像KenG所说的,如果你需要打破大型表格-考虑对它们进行分区。然后添加一些硬盘 :)

但是首先在您的数据库上运行SQL分析器,并优化索引和查询。通常处理数百万行数据不是什么大问题(除非您的客户需要实时计算超过其中一半的数据,此时分区也无法帮助)。

我知道这个答案很疯狂,但就是这样...

我目前面临的情况类似,需要在多个位置控制使用MS SQL Server的系统的数据库版本。

我现在正在使用Ruby on Rails ActiveRecord迁移来控制数据库版本。是的,我知道我们正在谈论Windows系统,但这对我来说很有效。 (顺便说一下,我的系统是用VB和.NET编程的)

我已经在每个服务器上安装了Rails,在需要更新数据库架构时,我将迁移文件复制到服务器上并运行rake db:migrate,这将将数据库更新到最新版本或回滚到所需版本。

作为副作用,您将拥有一组数据库迁移文件,使用独立于数据库的语言(在这种情况下是Ruby),您可以将其应用于其他数据库引擎,并将其放在源代码控制下。

我知道这是一个奇怪的解决方案,使用完全不同的技术,但学习新方法不会有损。您可以在此处找到更多信息。

自从我学会了Ruby on Rails,我已经成为了一名更好的.Net程序员。我之前在这里问过一个关于这种方法的问题。 问题链接





相关问题
热门标签