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

发布于 2024-07-12 05:09:12 字数 726 浏览 4 评论 0原文

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

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

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

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

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

什么工具或实践是否可以帮助您以更小的风险和更大的信心进行数据库迁移? 有没有什么好的书籍或互联网资源?

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

I have a C# application which works with an Oracle database and has been already shipped. Now it's time to ship out a new release. The C# object model have been revised and had an impact on the table structure.

If I ship out the new release, I need to take care of existing data. Just dropping tables and recreate these tables wouldn’t make any customers happy.

To counter this problem I have collected SQL scripts, which alters the previously released database structure to the new database structure. In the course of this, the data are migrated too. The SQL scripts are committed to a repository like C# source code. The patching of the database is tested on regular basis with the help of CruiseControl.NET. NUnit tests are run against the patched database to uncover mismatches between database tables and C# object model.

The whole procedure does work, but I have the feeling that this could be done better. I regard database migration as very critical. A shipped application, which doesn't work with a wrongly patched database, has no value. Losing data is inacceptable. These horror scenarios might make me think not to change the database at all. So it’s very important for me to have full confidence in the tools and practices I use.

Last week I stumbled over LiquiBase and I asked myself -- and now in SO:

What tools or practices can help to do database migration with lesser risks and more confidence? Are there any good books or internet resources out there?

I am especially interested in specific solutions to C# and Oracle, which might fit in the development procedure I have outlined above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤独岁月 2024-07-19 05:09:12

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

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

此过程使您能够:

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

Database upgrade scripts must be part of development process. Here is one way of keeping track about database schema upgrades:

  • create VERSION table in database that contains one record with version number
  • each time you make change to database schema of your application you should:
    • create SQL script for creating, altering or dropping database objects
    • create SQL script for managing data changes that must be done with new data schema (e.g. insert defaults in new fields, insert default records in new tables, create script for splitting or merging tables, ...)
    • increment database version number
      • For each change I usually create one script named DbVerXXXX.SQL that contains all necessary upgrades (XXXX is version number). Also, I do changes in small steps - change DB schema only for next change you will do in your application. Don't create database upgrade that will take weeks or months of work to upgrade your application.
  • create script that will upgrade your user's database to new version:
    • script should check current version of database and then execute database upgrade scripts that will convert schema to required level
    • change version number in VERSION table

This process enables you to:

  • put all database schema changes under source control, so you have complete history of changes
  • try and test your upgrade scripts on test databases, before you ship it to customer
  • automatically upgrade user databases with confidence
少跟Wǒ拽 2024-07-19 05:09:12

您可能想要研究一些可用的数据库冗余技术,例如 Oracle Dataguard。 我相信它特别具有一些可以帮助解决此类场景的功能。

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

You may want to look into some of the database redundancy technologies available out there, such as Oracle Dataguard. I believe it in particular has some features that could help with this type of scenario.

Regardless of your technology however, anytime you have a schema change in the database you will obviously run some risk. One simple practice that you can always perform is to create a copy of the database, put it on a different server, and run your upgrade procedure there first to work through your bugs. When working with customers in similar scenarios we've typically done that with them, just to alleviate their concerns and iron out any potential issues before performing the operation on the live environment.

仅此而已 2024-07-19 05:09:12

为了确保在更改数据库时不会丢失数据,您可以创建脚本来确认新结构和旧结构包含相同的逻辑数据。 例如,假设数据库的版本 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

或 OCT.Address4 != A.Address4

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

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

To make very sure that you are not losing data when you alter a database, you can create scripts to confim the new structure and the old one contains the same logical data. For example, say version 1 of database looks like this (pseudo code)

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

In version 2, you want to be able to allow customers to have more than one adress so you move the address fields into a new table:

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

You move the addresses from Customer table into the new address table like this:

INSERT Address
CustomerID ,
AddressLine1 ,
AddressLine2 ,
AddressLine3 ,
AddressLine4 

SELECT
*
FROM Customer

Then you remove the redundant address fields from Customer:

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

So far so good. But how do I know that the new Address table contains the exact same addresses as the old Customer table. It would be very easy for the whole process to run and somehow scramble the address so that Customers effectively changed adresses with each other. The code could pass all tests, but we will have destroyed our clients data as they no longer know where their customers live.

We can confirm the move of address fields works by running

If this returns any records, the upgrade failed because some customers didn't get their address moved:

SELECT 
 *
FROM

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

If this returns any record, the upgrade failed because addresses were scrambled

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

You can additionally check that the new address table only contains 1 address for each customer

SELECT
 CustomerID
 , COUNT(AddressID)
FROM
 Address
GROUP BY
 CustomerID
HAVING
 COUNT(AddressID) >1
情栀口红 2024-07-19 05:09:12

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

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

查看:

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

I fully agree with @Zendar that you must have proper versioning of your migration scripts, and that requires versioning metadata included in your database. Your scripts will modify your schema while updating the versioning information. This is how most applications update their database schemas.

That said, his process is a little too manual, and you might be interested in more automated tools to this end.

Check out:

You could also consider the ideas in these tools and develop your own.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文