【问题标题】:Migrating an Oracle database with a C# application attached to it: How to manage database migration?迁移带有 C# 应用程序的 Oracle 数据库:如何管理数据库迁移?
【发布时间】:2009-01-31 17:01:30
【问题描述】:

我有一个可与 Oracle 数据库配合使用的 C# 应用程序,并且已经交付。现在是发布新版本的时候了。 C# 对象模型已经过修改,并对表结构产生了影响。

如果我发布新版本,我需要处理现有数据。只是删除表并重新创建这些表不会让任何客户满意。

为了解决这个问题,我收集了 SQL 脚本,它将以前发布的数据库结构更改为新的数据库结构。在此过程中,数据也被迁移。 SQL 脚本被提交到类似于 C# 源代码的存储库中。在 CruiseControl.NET 的帮助下定期测试数据库的补丁。 NUnit 测试针对已修补的数据库运行,以发现数据库表和 C# 对象模型之间的不匹配。

整个过程确实有效,但我觉得这可以做得更好。我认为数据库迁移非常关键。一个无法与错误修补的数据库一起运行的应用程序没有任何价值。丢失数据是不可接受的。这些可怕的场景可能会让我觉得根本不要更改数据库。因此,对我使用的工具和实践充满信心对我来说非常重要。

上周我偶然发现了LiquiBase,我问自己——现在是这样:

哪些工具或实践可以帮助您以更小的风险和更有信心的方式进行数据库迁移?那里有什么好书或互联网资源吗?

我对 C# 和 Oracle 的特定解决方案特别感兴趣,它们可能适合我上面概述的开发过程。

【问题讨论】:

    标签: c# database oracle migration


    【解决方案1】:

    数据库升级脚本必须是开发过程的一部分。这是跟踪数据库架构升级的一种方法:

    • 在数据库中创建 VERSION 表,其中包含一条带有版本号的记录
    • 每次更改应用程序的数据库架构时,您应该:
      • 创建用于创建、更改或删除数据库对象的 SQL 脚本
      • 创建 SQL 脚本以管理必须使用新数据架构完成的数据更改(例如,在新字段中插入默认值、在新表中插入默认记录、创建用于拆分或合并表的脚本......)
      • 增加数据库版本号
        • 对于每个更改,我通常会创建一个名为 DbVerXXXX.SQL 的脚本,其中包含所有必要的升级(XXXX 是版本号)。此外,我会以小步骤进行更改 - 仅为您将在应用程序中进行的下一次更改更改数据库架构。不要创建需要数周或数月的工作来升级您的应用程序的数据库升级。
    • 创建将用户数据库升级到新版本的脚本:
      • 脚本应检查当前数据库版本,然后执行将架构转换为所需级别的数据库升级脚本
      • 更改 VERSION 表中的版本号

    此过程使您能够:

    • 将所有数据库架构更改置于源代码控制之下,以便您拥有完整的更改历史记录
    • 尝试在测试数据库上测试您的升级脚本,然后再将其发送给客户
    • 自信地自动升级用户数据库

    【讨论】:

      【解决方案2】:

      您可能想研究一些现有的数据库冗余技术,例如Oracle Dataguard。我相信它特别具有一些可以帮助解决这种情况的功能。

      但是,无论您采用何种技术,只要您在数据库中更改架构,您显然都会面临一些风险。您始终可以执行的一种简单做法是创建数据库的副本,将其放在不同的服务器上,然后首先在那里运行升级过程以解决错误。在与类似场景中的客户合作时,我们通常会与他们一起这样做,只是为了减轻他们的担忧并在对实时环境执行操作之前解决任何潜在问题。

      【讨论】:

        【解决方案3】:

        为了确保在更改数据库时不会丢失数据,您可以创建脚本来确认新结构和旧结构包含相同的逻辑数据。例如,假设版本 1 的数据库看起来像这样(伪代码)

        CREATE TABLE Customer
        CustomerID INT, 
        FirstName string,
        Surname string,
        AddressLine1 string,
        AddressLine2 string,
        AddressLine3 string,
        AddressLine4 string
        

        在版本 2 中,您希望能够允许客户拥有多个地址,因此您将地址字段移动到新表中:

        CREATE TABLE Address
        AddressID INT,
        CustomerID INT,
        AddressLine1 string,
        AddressLine2 string,
        AddressLine3 string,
        AddressLine4 string
        

        您将客户表中的地址移动到新地址表中,如下所示:

        INSERT Address
        CustomerID ,
        AddressLine1 ,
        AddressLine2 ,
        AddressLine3 ,
        AddressLine4 
        
        SELECT
        *
        FROM Customer
        

        然后您从客户中删除多余的地址字段:

        ALTER TABLE Customer
        DROP COLUMNS 
        AddressLine1 ,
        AddressLine2 ,
        AddressLine3 ,
        AddressLine4 
        

        到目前为止一切顺利。但是我怎么知道新的地址表包含与旧的客户表完全相同的地址。整个过程很容易运行并以某种方式打乱地址,以便客户有效地相互更改地址。该代码可以通过所有测试,但我们将销毁我们的客户数据,因为他们不再知道他们的客户住在哪里。

        我们可以通过运行确认地址字段的移动工作

        如果这返回任何记录,则升级失败,因为一些客户没有移动他们的地址:

        SELECT 
         *
        FROM
        
          OldCustomerTable  OCT LEFT JOIN Address A
          ON OCT.CustomerID = A.CustomerID
        WHERE 
          A.CustomerID IS NULL
        

        如果返回任何记录,则升级失败,因为地址被打乱了

        SELECT
          *
        FROM 
         OldCustomerTable  OCT INNER JOIN Address A
          ON OCT.CustomerID = A.CustomerID
        WHERE
          OCT.Address1 != A.Address1 
          OR OCT.Address2 != A.Address2
          OR OCT.Address3 != A.Address3
        

        OR OCT.Address4 != A.Address4

        您还可以检查新地址表是否仅包含每个客户的 1 个地址

        SELECT
         CustomerID
         , COUNT(AddressID)
        FROM
         Address
        GROUP BY
         CustomerID
        HAVING
         COUNT(AddressID) >1
        

        【讨论】:

          【解决方案4】:

          我完全同意@Zendar 的观点,即您必须对迁移脚本进行适当的版本控制,这需要在数据库中包含版本控制元数据。您的脚本将在更新版本信息时修改您的架构。这是大多数应用程序更新其数据库架构的方式。

          也就是说,他的过程有点过于手动,您可能会对为此目的更自动化的工具感兴趣。

          退房:

          您还可以考虑这些工具中的想法并开发自己的想法。

          【讨论】:

            猜你喜欢
            • 2014-08-24
            • 1970-01-01
            • 2016-08-22
            • 1970-01-01
            • 1970-01-01
            • 2011-01-28
            • 2013-10-02
            • 2014-12-09
            相关资源
            最近更新 更多