1

我们有一些客户拥有大型数据集,在我们的升级过程中,我们需要修改各种表的架构(添加一些列,重命名其他列,偶尔更改数据类型,但这种情况很少见)。

以前我们一直在使用新模式的临时表,然后删除原始表并重命名临时表,但我希望通过使用ALTER table ...来显着加快速度。

我的问题是我需要考虑哪些数据完整性和错误处理问题?我应该在事务中包含对表的所有更改(如果是,如何?)还是 DBMS 会保证 ALTER 操作的原子性和完整性?

我们已经强烈建议客户在开始升级之前备份他们的数据,因此这应该始终是一个后备选项。

我们需要以 SQLServer 2005 和 Oracle 为目标,但显然如果它们需要不同的方法,我可以添加条件代码。

4

4 回答 4

3

仅针对 Oracle 的评论:

  • 表更改是 DDL,因此事务的概念不适用 - 每个 DDL 语句在操作期间锁定表并且成功或失败。

  • 添加(可为空!)列或重命名现有列是一个相对轻量级的过程,如果可以获取表锁,则不应该出现任何问题。

  • 如果您正在添加/修改约束(NOT NULL 或更复杂的检查约束),Oracle 将检查现有数据以验证约束,除非您将 ENABLE NOVALIDATE 子句添加到约束 DDL。对于大型表,现有数据的验证可能是一个漫长的过程。

  • 如果您正在编写脚本以将升级作为 SQL*Plus 脚本运行,请使用“whenever sqlerror exit sql.sqlcode”指令在第一次失败时中止脚本以检查部分实施,从而省去很多麻烦升级更容易。

  • 如果必须在无法控制事务或错过它们的实时系统上执行升级,请考虑使用 Oracle DBMS_REDEFINITION 包,它会自动创建临时表和触发器的临时配置,以在重新定义表时捕获正在进行的事务在“背景”中。警告 - 此选项的大量工作和陡峭的学习曲线。

于 2009-06-15T12:20:03.730 回答
1

如果您使用的是 SQL Server,则 ddl 语句是事务性的,因此请包含在事务中(尽管我认为这不适用于 Oracle)。

我们将升级拆分为具有特定功能的单个补丁。应用了哪些补丁程序放在一个database_patch_history表格中,很容易看到应用了哪些补丁程序以及如何回滚它们。

正如您所说,在开始之前进行备份很重要。

于 2009-06-15T09:45:08.877 回答
1

过去我不得不做这样的改变,并且一直对数据丢失非常偏执。为了帮助减轻这种风险,我一直对“沙盒”数据库进行大量测试,这些数据库尽可能地在模式和数据中镜像目标数据库。在推出之前尽可能多地测试该过程,就像您对应用程序的任何其他区域进行测试一样。

于 2009-06-15T12:39:09.427 回答
0

如果您大幅更改列的任何数据类型,例如将 VARCHAR 更改为 INT,DBMS 将出现恐慌,您可能会丢失该数据。幸运的是,如今的 DBMS 足够智能,可以在不丢失数据的情况下进行一些数据类型转换,但是您不想在进行更改时冒损坏任何数据的风险。

您不应该通过重命名列来丢失任何数据,并且绝对不会通过添加新列,这是当您移动数据时您必须关注的。

首先,备份整个表,包括模式和数据,这样您就可以立即回滚到以前的模式。其次,看看你试图做出的改变,看看它们有多么激烈——试着弄清楚到底需要改变什么。如果您要进行数据类型转换,首先将该数据推送到具有 3 列的中间表,外键(id 或任何您可以定位行的内容)、旧数据和新列。然后要么直接将旧数据推送到新列,要么在应用程序级别进行转换。

当一切都在正确的类型中并且一切都成功时,运行 ALTER 语句并重新填充数据库!做起来很简单,只需要一个合乎逻辑的思考过程。

于 2009-06-15T09:55:31.660 回答