【问题标题】:Error handling and data integrity when changing table schema更改表架构时的错误处理和数据完整性
【发布时间】:2010-11-02 23:20:45
【问题描述】:

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

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

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

我们已经强烈建议客户在开始升级之前备份他们的数据,以便始终作为后备选项。

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

【问题讨论】:

    标签: sql-server oracle schema alter-table data-integrity


    【解决方案1】:

    如果您使用的是 SQL Server,那么 ddl 语句是事务性的,因此请封装在事务中(不过我认为这不适用于 Oracle)。

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

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

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

      • 我不会担心在数据类型转换上丢失太多数据。只需在测试数据库上尝试一下,看看它是否出错。这些类型的脚本应该得到与应用程序一样多的测试关注,因此如果某些东西不起作用,您会在部署到实际应用程序之前很久就发现。
      • Oracle 永远不会恐慌 :) ... 但它会报告 ORA-01439 “要修改的列必须为空才能更改数据类型” ... 要更改数据类型,您必须添加一个新列,更新它,删除旧列,然后重命名新列。
      【解决方案3】:

      仅适用于 Oracle 的评论:

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

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

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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-26
          • 2018-04-18
          • 2011-06-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-14
          • 1970-01-01
          相关资源
          最近更新 更多