误删的恢复: DBA的噩梦

本文是对Paul Pendle的Dropped object recovery: A DBA’s nightmare的翻译。文章主要讲了因为数据库对象的依赖关系,以及数据库系统对于关联对象删除的处理逻辑,导致了误删之后恢复工作的复杂性。本文的环境是IBM的z/OS,DB2,但是一些思路在关系型数据库上应该具有普适性。

此分割线以下是全部译文,自己翻译,欢迎勘误。


关系型数据库管理系统(RDBMS)会维护数据库对象之间的逻辑关系。 这种逻辑关系类似于父子关系。原则上,RDBMS中不允许(或者至少不应该)出现“孤儿”,这就意味着,如果父节点被删除了,那么所有相关的或相依赖的子节点,都需要被移除或删除。这非常合理,试想,如果连表都没有了,建在表上的index怎么还会有存在的必要呢。

多数的数据库设计者都认为,数据库中的相互关联的对象应该遵从引用完整性和主外键约束。当然,这在RDBMS中也是至关重要的一部分,RDBMS中的依赖性必须被很好的维护。

但是,RDBMS需要维护和管理有太多太多的依赖性关系,有些很容易被大意的使用者忽视。表1中就列举出了在z/OS的DB2中的这样一些组件,这些组件和其他既有组件相关或者相依赖。

List of objects with dependencies

AliasIndexStored procedure
ConstraintMQTSynonym
ClonePackageSYSCOPY entries
Data typePlanTable space
DatabaseProcedureTrigger
FunctionRoleUDF
Global variableSequenceView
GrantsSequence alias

DB2怎么处理被删除的对象

如果你删除了一个表,DB2会自动地把相关的索引,触发器,授权,师徒,代名词都给删除,不留下任何一个相关对象。这减少了DBA很多工作量。

但是当DBA误删了一个表时,DB2的这种处理方式就会出现问题了,DB2还是会删除与这个表相关的所有对象。这时,DBA就一脸懵逼了。这时,他不仅要考虑怎么恢复所有丢掉的对象,还得考虑怎么恢复表中所有的数据。

z/OS中的DB2恢复功能并不能恢复一个被删除的表,即使之前用SYSCOPY做了备份。这是为什么呢?这是因为,在执行恢复操作之前,DB2的目录中应该存在这个要恢复的表的定义。

下图描述的是之前列举出来的对象的最大的层级依赖关系:

数据库对象层级关系图

如图所示,删除一个database,table space,或者table后,数据库所需要做的清理工作也就最大,因此,如果误删了这几种对象,再尝试恢复它们的时候所付出的代价也就最大。接下来,本文会对这个依赖关系树图做更详细地解释。

误删的可能原因

设想,如果我们我们在生产环境中做了充足的安全措施,来确保程序员或数据库用户不会误删数据库对象,那么,误删还会发生吗,还可能在什么情况下发生?其实,误删通常是因为DBA的失误。

因为DBA总是不得不使用较少的资源来完成较多的任务,所以事故发生的可能性就会相对较高。想想他们一天得盯着多少块屏幕吧,这样你就更容易体会到,误把生产环境的屏幕看成了测试环境的屏幕从而误删了生产环境的table,这样的概率有多大。

即使误删的是测试环境上的对象,也必须得做还原,因为测试环境上的数据也非常宝贵,并且,这样的恢复工作会耗费大量的时间和精力。

预防误删

怎么样才能降低误删database,table space或table的概率呢?一个解决方案,就是移除DBA对于生产环境数据的特权。换句话说,就是没有所谓的DBA权限(类似SYSADM或DBADM)了。如果使用移除DBA权限的方案,带来的坏处就是,在一些情况下管理员不能做出快速反应了。禁用或者启用DBA的权限,总是需要来来回回重复这样的流程,会显得一团糟。

更好的选择应该是,在生产环境上限制DROP操作。你可以在创建table是使用RESTRIC ON DROP命令来做控制。如下:

CREATE TABLE my.table
( my col INTERGER)
WITH RESTRICT ON DROP;

如果table已经存在了,可以使用ALTER命令把RESTRICT ON DROP限制给加上。

ALTER TABLE my.table ADD RESTRICT ON DROP;

当尝试DROP一个有此限制的table时,会提示一个异常:

DSNT408I SQLCODE = -672, ERROR: OPERATION DROP NOT ALLOWED ON TABLE my.table

如果你真的需要删除这个table,你必须先移除这个限制。用下面的ALTER命令来做:

ALTER TABLE my.table DROP RESTRICT ON DROP;

现在这张table就能被drop了。当对此table的所有操作都完成了之后,应该再回复此table的RESTRICT ON DROP状态。

如果在生产环境上的所有table上都加了这个约束,那么你得做好心理准备,在做常规的drop和recreate操作时,你必须得用ALTER命令添加或移除RESTRICT ON DROP限制。

下面的示例SQL语句做了如下操作:读SYSIBM.SYSTABLES,并生成能在TESTDB中所有table上添加RESTRICT ON DROP限制的SQL语句。

SELECT 'ALTER TABLE ' || CREATOR || '.' || NAME ||
' ADD RESTRICT ON DROP;'
FROM SYSIBM.SYSTABLES
WHERE DBNAME = 'TESTDB'
AND TYPE = ‘T’;

恢复删除的table

如果确实不小心删除了一张重要的table,应该怎么恢复呢?最完整的方案,就是重新创建一张table和之前提到的那些依赖对象,并且找到一个有效的方法,把table中的数据都恢复了。

以下是恢复的五个关键步骤:

  1. 使用你之前保存的data definition language(DDL)来重新创建table
  2. 到所有被删了依赖对象,然后使用DDL恢复这些对象
  3. 使用data control language(DCL)重建所有的安全控制
  4. 通过某种方式恢复数据,通常使用镜像拷贝或者时间点拷贝
  5. 查看log,通过比对拷贝的时间点到table被删除的时间点之间的数据变动,更新数据

如果环境维护的比较好的话,第1步到第4步是可行的。如果table被创建之后还经历过一系列的修改,必要的话,需要把这些修改的DDL和最初的merge在一起。同时,不要忘记添加DB2授权。如果授权是通过GRANT选项赋上的,你就必须找到接受授权的那个最初的ID(GRANTEE)。如果这些都准备就绪,你应该能够重建这张table的结构和组件。

但是,还有table的数据需要还原。第4步和第5步是处理table数据的。

还原丢失的数据

要还原数据,你得有一个误删table的镜像拷贝。如果你有这样的拷贝,就把它重载到那张新建的table中。注意,如果一个table space被删除了,那么这个table space中的所有table的所有对象都已经从SYSIBM.SISCOPY中删除了。这种情况下,要找到对应的镜像拷贝的名字就有些难办了。如果你当时使用了DB2模板功能,那么你能区分出来哪些是你需要的镜像拷贝。如果你当时没有使用,你就必须使用DSN1LOGP来访问log,来定位哪些镜像拷贝是你需要的。

假设你找到了相应的镜像拷贝,数据也就可以被装载到了新建的table中了。当然,此时恢复的数据,只是镜像拷贝被生成的那个时间点的数据,而不是table被误删的那个时间点的,这期间的数据变动都丢失了。取决于数据的重要性和table的变动频度,这些数据的丢失可能是你的公司所不能接受的,尤其当这个镜像拷贝的被创建的时间太过“久远”。

当你恢复了所有丢失的数据后,你还需要更新从误删一直到现在,table中所有的数据变动。

继续更新数据

为了更新table的数据状态(第5步),你需要利用log更新从table被备份到被删除期间的数据。因为log记录的是完全不同对象,所以没有相应的DB2功能可以直接处理log并恢复数据。

但是,你可以使用z/OS上的DB2 Log分析工具和DB2恢复助手来分析和被删除对象相关的active/archive的log,从而最小化新table数据恢复工作的工作量。

这些工具会取出和被删除对象有关的log,并把这些log应用在新创建的对象上。当DB2 Log分析工具只能从log恢复数据,而DB2恢复助手则提供一个易用的接口,能够实现以上的五个步骤,自动地完成端对端的数据恢复。

所以,即使你没有保留所有的恢复所必需的DDL,DB2恢复助手也能够通过分析log记录就帮你创建新table(恢复所有的依赖对象)。最新版本的恢复助手比手动的UNLOAD/LOAD有更完善的流程,而且速度更快。利用恢复助手,我们能直接通过log把误删的table恢复到新建的table上。如果你缕清它究竟帮你处理了多少的对象,权限和活动,你就能感受到它的功能是多么的感人。

当把数据恢复到最新的状态后,你应该在table上执行RUNSTATS命令,而且要重新绑定那些因为table被删除而失效的DB2包。你同样需要确认这些包的访问路径是最佳的。

总结

任何环境下的误删恢复都是一个不小的挑战。未雨绸缪,做好预防措施。当误删真的发生了,不用慌张,z/OS上的DB2相关工具能让你如释重负,如鱼得水。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值