代码之家  ›  专栏  ›  技术社区  ›  Henk Holterman

将多个数据库迁移并合并为一个数据库

  •  -2
  • Henk Holterman  · 技术社区  · 16 年前

    在更新项目中,我必须执行以下操作:

    当前的计划是将每个旧数据库移动到1个数据库中的单独模式中。

    这意味着我们还必须更改当前的SP和视图,我们现在有:

    SELECT OrderId, OrderDate FROM Sales.dbo.Orders
    

    SELECT OrderId, OrderDate FROM Sales.Orders
    

    问题是:我们如何做到尽可能自动化?

    6 回复  |  直到 16 年前
        1
  •  6
  •   Brent Ozar    16 年前

    几年前我就这样做了,我遇到了一些你想知道的问题。

    • 您希望所有对象都以数据库A中的SQL 2005结尾(我们将其称为目标)
    • 您希望最终摆脱数据库B和C(旧的源代码)

    以下是我从中学到的惨痛教训:

    提前在目标中构建新对象。 即使它们没有在你的实时制作应用程序中被查询,现在就开始构建它们。这样,您就可以在其中填充假测试数据,以便提前测试您的应用程序。是的,这意味着混合现场和测试数据,但坦率地说,你已经在没有网络的情况下工作了。不过,要小心标识字段,因为目标数据库和源数据库中可能会出现具有相同标识号但数据不同的冲突记录。

    提前在目标中创建视图。 您提到您已经有了一些视图,这些视图已经进行了跨数据库查询。现在将这些视图从源视图复制到目标视图,并告诉任何其他开发人员(报表人员、超级用户)开始引用目标视图。这不会加快你自己的工作,但会加快他们的工作。如果您能够验证它们是否只命中目标(即使目标视图仍然指向源代码中的表),那么在迁移当天就可以更轻松地进行故障排除。然后,您可以开始提前拒绝对源代码视图的权限。

    提前同步表。

    检查源数据库之间的记录冲突。 听起来这一条并不特别适用于你,但我在这里记下了它,以防其他人进行合并,他们正在阅读它以获取提示。如果有多个源数据库,请转储对象列表。如果有两个同名的对象,请检查它们的模式。我曾经处理过这样的实例,它们在每个数据库中都有一个State或Region表,它们应该是相同的,但它们的主键有标识字段。每个子表(如链接到区域表的客户)都通过主键(标识字段)引用父表(区域)——主键在数据库之间不匹配。在这种情况下,明智的做法是在迁移日之前提前设置一个停机窗口,用手动更新脚本清理这些记录。

    1. 更改标识字段(如果它们是查找表,则可以关闭标识内容,只使用手动指定的pk号运行)
    2. 修改Region表以添加一个新的ID字段,与它将成为的内容相匹配,并添加一个旧的ID字段,显示它以前是什么
    3. 更新区域表,使真实ID字段现在具有NewID值,而OldID字段具有区域以前的值。(你可能会搞砸一些事情,比如错过一张你不知道的儿童桌,你会想知道它曾经是什么。)

    将迁移分解为多个部分。

    如果您不使用SQL2005新的即时文件初始化,那么数据文件增长需要相当长的时间。如果您有选择,请启用即时文件初始化,然后增加数据文件以确保它们不被分割。如果它们只是在迁移期间自然生长,它们可能会变得支离破碎。如果不能使用即时文件初始化,则仍然需要预增长文件,但您希望在低活动期间提前这样做,以加快维护窗口。

    在迁移日,每次运行一个表或更小的表。 您希望使插入事务尽可能紧凑。插入事务越小,事务日志中所需的空间就越小。请记住,即使在简单模式下,事务日志也会随着insert语句而增长。在每一轮插入之后,进行一次完整性检查,以确保它们正常工作,并且不会耗尽数据文件或t-log文件的驱动器空间。

    源数据库的其他选项包括:

    • 重命名它们,这样你仍然可以查询它们,但应用程序不会触及它们
    • 分离它们,但保持文件可用,以防需要进行故障排除

    更新完成后,重新生成索引&目标统计数据。

    最后一个只是我的两分钱,但听起来你需要做大量的工作,从3个数据库,每个数据库1个模式,到1个数据库3个模式。如果你对3个模式的东西不太确定,你可能会考虑使用1个模式——否则你会在接下来的路上再进行一次混乱的返工。如果您有特定的安全需求,那么3个模式是有意义的,但除此之外,请确保您得到了想要的回报。现在是进入一个模式的好时机。

        2
  •  2
  •   Sam    16 年前

    您可以给Redgate SQL Compare和Data Compare一个快照。它们有一个模式映射特性,可以让您将dbo模式映射到另一个模式中的sales模式,然后移动表和进程。这将使您不必使用SQL导出向导。不过,您仍然需要重构其他对象。

    我喜欢这两个工具。


    编辑:


    编辑: 此外,它们还提供了SQL重构,可以进行“智能”重命名。分数

        3
  •  1
  •   Kristen    16 年前

    您是否可以有一个名为SALES的虚拟数据库,其中有一个名为[Orders]的视图:

    CREATE VIEW Sales.dbo.Orders
    AS
    SELECT OrderId, OrderDate, ...
    FROM CombinedDatabase.Sales.Orders
    

    仍然有效。

    如果你能有这样的视图日志,它们被使用,这将使你能够修复调用它们的代码!!但我想不出一个方法来做到这一点;然而,您可以依次禁用每个,运行一些测试,修复任何损坏的,然后继续下一个。。。这样就可以通过重构来消除它们,但在此过程中,应用程序基本上可以正常工作。

        4
  •  1
  •   Tim Cooper    13 年前

    1. 您有三个不同的数据库(即销售、生产、库存)
    2. 您希望将所有三个数据库中的所有表/进程放在一个数据库中(即SaleManInv)

    1. 将一个进程从SQLServer2000DB导出到SQLServer2005DB,以确定是否需要删除交叉引用的“.dbo.”部分。
    2. 将所有程序导出为文本文件(所有程序的文件夹相同)
    3. 使用带有“搜索并替换文件”(我使用PSPAD)的文本编辑器,将所有“Sales.dbo.”替换为“SaleManInv.dbo.”,然后将所有“Iventory.dbo.”替换为“samemaniv.dbo.”等,以将所有引用转换为新数据库。
    4. 然后在新数据库中运行导出和修改的过程。

    这有意义吗?:-)

        5
  •  1
  •   Andrew Barber Eric Lafortune    12 年前

        6
  •  0
  •   Flinkman    16 年前

    我想知道是不是同样的数据。无论如何。我将创建一个名为“SourceSystem”的新列。因此,当老板来追赶时:

    “-2004年databasesystem1和db2之间的销售差异是多少”。

    那你就可以回答了。再过一两年,如果这个问题不出现的话。您可以删除该列。合并数据将删除数据的来源。