迁移附有C#应用程序的Oracle数据库:如何管理数据库迁移?

3
我有一个使用Oracle数据库的C#应用程序已经发布。现在是发布新版本的时候了。C#对象模型已经进行了修订,并对表结构产生了影响。
如果我发布新版本,我需要处理现有数据。仅删除表并重新创建这些表不会让任何客户感到满意。
为了解决这个问题,我收集了SQL脚本,用于将以前发布的数据库结构更改为新的数据库结构。在此过程中,数据也会被迁移。 SQL脚本像C#源代码一样提交到存储库中。使用CruiseControl.NET定期测试数据库的修补程序。运行NUnit测试以发现数据库表和C#对象模型之间的不匹配。
整个过程确实有效,但我觉得这可以做得更好。我认为数据库迁移非常关键。一个不与错误修补的数据库一起工作的发布应用程序没有价值。数据丢失是不可接受的。这些恐怖的情景可能使我考虑根本不更改数据库。因此,我使用的工具和实践必须完全可靠。

上周我偶然发现了LiquiBase,我自问——现在想问 SO:

有哪些工具或实践可以帮助更加有信心地进行数据库迁移并减少风险?是否有好书籍或网络资源可用?

我特别关注适用于 C# 和 Oracle 的特定解决方案,这可能符合我上述的开发流程。

4个回答

5

数据库升级脚本必须成为开发过程的一部分。以下是一种跟踪数据库模式升级的方法:

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

此过程使您能够:

  • 将所有数据库模式更改放在源代码控制下,以便您完整地了解更改历史记录
  • 在向客户发送之前,在测试数据库上尝试和测试升级脚本
  • 自信地自动升级用户数据库

0

您可能想要了解一些可用的数据库冗余技术,例如Oracle Dataguard。我相信它特别具有一些功能,可以帮助处理这种类型的情况。

无论使用何种技术,每当数据库中有模式更改时,显然都会存在一定风险。您可以始终执行一个简单的实践,即创建数据库副本,将其放置在不同的服务器上,并首先在那里运行升级过程以解决错误。在与类似情况的客户合作时,我们通常会与他们一起执行此操作,以缓解他们的担忧并消除任何潜在问题,然后再在实际环境中执行该操作。


0

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

话虽如此,他的过程有点太手动化了,你可能会对更自动化的工具感兴趣。

请查看:

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


0
为了确保在更改数据库时不会丢失数据,您可以创建脚本来确认新结构和旧结构包含相同的逻辑数据。例如,假设数据库的第一个版本看起来像这样(伪代码):
CREATE TABLE Customer
CustomerID INT, 
FirstName string,
Surname string,
AddressLine1 string,
AddressLine2 string,
AddressLine3 string,
AddressLine4 string

在第二个版本中,您希望客户能够拥有多个地址,因此将地址字段移动到一个新表中:
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 

到目前为止一切都很好。但是我如何知道新的Address表包含与旧的Customer表完全相同的地址。整个过程很容易运行并以某种方式混淆地址,以便客户 effectively更改了彼此的地址。代码可能通过所有测试,但我们将破坏我们客户的数据,因为他们不再知道客户居住的地方。

我们可以通过运行以下命令来确认地址字段的移动是否有效

如果返回任何记录,则升级失败,因为某些客户未能将其地址移动:

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

或 OCT.Address4 != A.Address4

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接