您采取什么措施来避免在大型数据库中错误地更新数据?


20

在进行任何生产部署之前,通常的建议是先备份数据库。这样,如果新更新存在一些可能导致潜在数据丢失或逻辑数据损坏的问题,则您仍具有备份以比较和更正旧记录。

但是,这可以很好地工作,直到数据库大小达到几GB。一旦数据库很大,备份就需要很长时间才能完成。在这种情况下应遵循哪些最佳实践,以避免由于代码部署中的逻辑问题而导致逻辑数据损坏?


11
备份不仅适用于部署时。我的意思是,您的数据丢失仅是一次磁盘崩溃,而这些变化是不可预测的,并且可能在今天或明天发生。(突袭阵列不是答案,它们也会崩溃。)
Pieter B,

10
我想改一下这个问题,问题不是备份需要花费很长时间,而是如果更新发生灾难性故障,则可能需要进行恢复,这可能会长时间阻止生产。因此,您真正需要的是一种减少更新期间失败风险的策略。
布朗

1
我在这里同意@DocBrown。避免数据损坏和备份时间过长实际上是两个独立的问题。
罗比·迪

1
当您迅速接受时,您得到的输入就不会太多。
狗仔队

1
您是什么意思“代码部署中的逻辑问题”?
狗仔队

Answers:


25

作为定期为客户更新生产数据库以进行软件升级的人员,我告诉您,最大程度地减少错误的最佳方法是使更新尽可能简单。

如果您可以对所有记录而不是特定记录进行更改,则更可取。

换句话说,如果为您提供了需要更改其状态的记录ID列表,则您应该问自己,为什么要在程序的上下文中进行更新。这可能是的10条记录,你需要更新,该表只具有 10个元素。因此,您应该问自己,从概念上讲,您是否正在做的就是更新所有记录的状态。

如果可以插入,则更可取。

添加记录的行为是独立的。我的意思是添加记录只有一个副作用,那就是存在以前不存在的记录。因此,除非您添加不应该存在的记录,否则应该没有问题。

如果可以避免删除,那是可取的。

如果要执行删除操作,则要删除的数据如果没有备份将无法恢复。如果可能,请尝试组织数据,以便可以通过更改记录的状态而不是物理删除记录来禁用记录。一旦确定没有问题,多余的数据可以放在分区中,也可以稍后将其完全删除。

制定一致的更新策略。

如果您需要更新记录,则可能发生以下几种情况之一:

  1. 您的记录不存在。
  2. 您的记录存在,但已被更改。
  3. 您的记录存在并且需要更改。

您需要制定一项政策来确定如果某些事情没有按计划进行,应采取的措施。为简单起见,您应该始终保持一致,并在这种情况下(不仅限于特定表)应用此策略。这使以后恢复数据变得更加容易。通常,我的策略是编写脚本,以便以后可以重新执行它。如果脚本失败,很高兴知道您可以进行适当的调整并重新执行,但是您可以自由选择最适合自己的策略。

后备

这绝不妨碍您在生产环境中执行任何更新之前执行备份!尽管有备份,但我认为必须使用备份还是失败的。即使在最坏的情况下也不会丢失数据。

结论

您并不总是能够以自己的方式拥有它。表架构不太可能由您决定,因此,这意味着您可以期望执行的更新类型既复杂又冒险。尽管您对此有任何发言权,但记住这些要点将有助于记住这些要点,因为这些要点使任何更新变得简单明了且没有重大风险。

祝好运!


我同意您所说的一切,但是当您有10条记录需要从10k更改为10且插入/更新所有记录都不可行时,我对您的交易想法感到好奇?
我在这里参加Winter Hats '18

然后,您只需更新10条记录。我说如果可以的话。我没有说要这样做,即使它破坏了客户的生产数据库。请听我的建议,加些盐。
尼尔

12

那时,您应该使用支持快照的商业级数据库系统(Oracle将其称为Flashback)-这正是它们的用途。

请记住,无论如何您都需要一个备份概念-拥有更多数据并不意味着您会放弃备份,因为备份变得困难,相反。您需要某种连续备份,例如基于具有自动故障转移功能的复制。


我并不是说我要删除备份。计划备份始终存在。问题更多地是临时备份,对于小型系统而言这不是问题。
Pritam Barhate

为了进一步阐述,这种思路来自NoSQL DB即服务平台。当它弹出时,实际上是在阅读Firestore文档。如果您需要异地逻辑一致的备份,这似乎非常昂贵。因此,我想知道成功的产品团队如何使用此类系统,以及他们如何确保不会发生逻辑数据损坏。
Pritam Barhate

@PritamBarhate:由于更新,您不需要“更多备份”。在人们使用该数据的生产数据库上,备份必须至少每天进行一次,无论有无更新。 还原是您的问题,您想在所有情况下都避免不必要的还原。
布朗

3
使用自动故障转移进行复制是冗余,对于磁盘而言,冗余不再是对RAID的备份策略。
Blrfl

1
有关备份和快照的所有优点,但是清理坏掉的数据库操作(如果在实现之前已添加了几个小时的新数据)可能非常困难,具体取决于场景和它所影响的其他系统(计划程序,其他数据库条目)依赖它,如果它跨越多个表,缓存,身份验证等)。我一直以为我将不得不使用备份,但始终至少至少不必尝试。
匿名企鹅

3

这是一个很大的领域-因此,希望这个问题能在相当短的时间内得到解决,但是,这超出了我的头脑(作为yuge数据库的前DBA):

集市/存储库

如果您有一个单独的更新数据库和每个人都使用的单独数据库,则可以减轻一些风险。这只是在进行了各种检查之后将数据从一个DB复制到另一个DB的情况。市场/存储库有时是这样描述的,但是您可能具有主/辅助,主/从属等。

源代码

对于可以改变一切,具有涉及一种源代码如何在数据被更新。每个数据库中有多少个数据库,但每个用户,角色,数据馈送,代码模块等可能都有一个。

创建/更新日期

跟踪发生错误的位置时,可以为每行创建和更新数据,这可以极大地帮助您。然后您可以一眼看到哪些行已更新。

ETL

如果数据库更新是数据工厂的一部分,则可以从平面文件中还原以前的年份。

后备

完全备份当然会占用很多空间,但是通常的情况是完全备份要定期执行(例如,每周一次),部分备份则要更频繁地进行(每天等)。

时间点恢复

根据所使用的RDBMS,一些支持时间点恢复。这使您可以回滚到知道良好状态的时间。但是,这确实需要大量存储空间,这会增加您想返回的距离。

审计

拥有审核表将告诉您谁(或什么)对行进行了更新。这可以为您提供一个良好的调查起点。

历史

对于某些关键表,在更新时会获取相关行的副本,因此可以根据需要还原数据。

资料验证

在存储数据之前,请确保对数据执行基本的验证检查-除了基本数据类型检查之外。

参照完整性

参照完整性不是灵丹妙药,但可以帮助确保数据结构良好。



2

很多时候,如果我们要进行“一次性”更新,则会备份生产并将其还原到测试服务器。然后,我们创建一套测试并进行一次测试。我们通过测试验证数据已更改,并且对更新将成功并以我们期望的方式修改数据感到满意。这称为空运行或试运行。我建议这样做。

这给每个人一个很好的感觉,那就是一次成功。我们无法保证100%,因为数据会从试运行之日起进行更新,但我们会提高信心和成功率。这也给出了由于我们使用生产副本而可能发生的任何问题的真实想法。现在,如果由于某种原因更新失败,我们总是可以在需要时先进行后台运行,然后再进行还原,但是我们应该已经找到并纠正了空运行的任何问题。

如果无法获取整个数据库(如果非常大),请尝试导出较小的样本量,然后根据实际数据运行更新(小试运行)。我希望尽可能使用整个数据集,以确保测试尽可能完整。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.