DB2 日常维护技巧,第 3 部分

来源:互联网 发布:图片浏览器 知乎 编辑:程序博客网 时间:2024/06/05 11:36

表的使用状态、用户连接、日志管理与数据恢复等

developerWorks文档选项将此页作为电子邮件发送

将此页作为电子邮件发送


级别: 初级

程永 (cyong@cn.ibm.com), 高级信息工程师, IBM
王雪梅 (xuemay_2000@163.com), 高级数据库工程师, 自由撰稿人

2008 年 12 月 12 日

本文主要介绍数据库管理员(DBA)在日常维护中遇上一些比较紧急的情况如何处理,如何形成自己的应急方案,以及在日常维护中需要注意哪些技巧。“ DB2 日常维护技巧,第 3 部分”主要包括如何快速查找没有索引的表,如何查找发生过全表扫描的表,如何强行中断用户连接,如何通过结果集创建表,如何进行单引号转换,DB2 备份历史文件损坏后如何处理,编译 SQL 语句时出现 SQL0101N 错误如何处理,如何恢复已经删除的表等。

快速查找没有索引表的办法

如果想快速查看系统中哪些表没有建立索引,可以通过查询系统视图 syscat.tables 和 syscat.indexes 来获得,比如我们想查看我们的示例数据库 SAMPLE 中有哪些表没有建立索引,可以在当前 DB2CLP 窗口中,发出 SELECT 命令检索系统视图 syscat.tables 和 syscat.indexes 来获得,具体如清单 7 所示:


清单 7. 快速查找没有索引的表的办法
C:/> db2 connect to sample 数据库连接信息数据库服务器 = DB2 / NT 9.1.0  SQL 授权标识 = RHETTE 本地数据库别名 = SAMPLE  C:/> db2 select tabname from syscat.tables where tabname not in             (select tabname from syscat.indexes)  TABNAME  - - - - - - - - - - - - - - - - - - - - - - - - - - -  ABC  ADEFUSR  CL_SCHED  DEPT  EMP  EMPACT  EMPPROJACT  EMP_ACT  IN_TRAY  ORG  PROJ  SALES  STAFF  STAFFG  TEST1  TEST2  TEST3  TEST4  TEST5  TEST6  TEST7_EXCEPTION  TEST8  TEST9  . . . . . . . . . . . . . . . . . .  354 条记录已选择。

命令成功完成。为了节省篇幅,清单 7 中只显示了部分结果。





回页首

查找发生全表扫描的表

我们在维护数据库的过程中,经常需要查看哪些表发生了全表扫描,发生的频率高不高,并把这些表根据快照监控中得到的 dynamic sql 对索引进行调整。我们可以利用 DB2 V9 提供的 db2pd 工具来完成这个操作。

下面我们继续在当前 DB2CLP 窗口中,发出“ db2pd -db sample-tcbstats ”命令,查找系统发生过的全表扫描的表,具体如清单 8 所示:


清单 8. 使用 DB2PD 查找发生过全表扫描的表
C:/> db2 connect to sample 数据库连接信息数据库服务器 = DB2 / NT 9.1.0  SQL 授权标识 = RHETTE 本地数据库别名 = SAMPLE  C:/> db2 select * from test1  ID  - - - - - - - - - - - - - - - - - - - - -  1  1  1  1  1  5 条记录已选择。 C:/> db2 select * from test2  ID NAMEJL  - - - - - - - - - - - - - - - - - - - - -  1 rhetteaaa  2 danielbbb  3 richardccc  4 henryddd  5 vivianeee  5 条记录已选择。 C:/> db2pd -db sample-tcbstats  Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:15:24  TCB Table Information:  Address TbspaceID TableID PartID MasterTbs MasterTab TableNameSchemaNm  0x7EF2AAA0 0 1 n/a 0 1 SYSBOOT SYSIBM  0x7EAAD4A0 0 5 n/a 0 5 SYSTABLES SYSIBM  0x7EAF1920 0 7 n/a 0 7 SYSINDEXES SYSIBM  0x7EAF38A0 3 6 n/a 3 6 TEST1 RHETTE  0x7EAF41A0 3 7 n/a 3 7 TEST2 RHETTE  0x7EAABBA0 0 13 n/a 0 13 SYSPLAN SYSIBM  0x7EAA5320 0 17 n/a 0 17 SYSDBAUTH SYSIBM  0x7EF2B4A0 0 22 n/a 0 22 SYSROUTINES SYSIBM  0x7EAA8BA0 0 31 n/a 0 31 SYSEVENTMONITORS SYSIBM  0x7EAA2AA0 0 33 n/a 0 33 SYSTABLESPACES SYSIBM  0x7EA918A0 0 86 n/a 0 86 SYSVERSIONS SYSIBM  0x7EF2FC20 0 102 n/a 0 102 SYSXMLSTRINGS SYSIBM  0x7EA90AA0 0 103 n/a 0 103 SYSXMLPATHS SYSIBM  0x7EAA7E20 0 113 n/a 0 113 SYSTASKS SYSIBM  0x7EAA02A0 0 134 n/a 0 134 SYSSURROGATEAUTHID SYSIBM  0x7EF2EB20 0 137 n/a 0 137 SYSROLES SYSIBM  0x7EAA3EA0 0 138 n/a 0 138 SYSROLEAUTH SYSIBM  0x7EA9D620 0 139 n/a 0 139 SYSCONTEXTS SYSIBM  0x7EA9F5A0 0 140 n/a 0 140 SYSCONTEXTATTRIBUT SYSIBM  0x7EAF02A0 0 141 n/a 0 141 SYSCOLLATIONS SYSIBM  0x7EA92420 0 144 n/a 0 144 SYSWORKLOADS SYSIBM  0x7EA93C20 0 145 n/a 0 145 SYSWORKLOADCONNATT SYSIBM  0x7EA94CA0 0 146 n/a 0 146 SYSWORKLOADAUTH SYSIBM  0x7EA99620 0 147 n/a 0 147 SYSSERVICECLASSES SYSIBM  0x7EA9C220 0 150 n/a 0 150 SYSWORKACTIONSETS SYSIBM  0x7EA96220 0 152 n/a 0 152 SYSTHRESHOLDS SYSIBM  0x7EA978A0 0 153 n/a 0 153 SYSHISTOGRAMTEMPLA SYSIBM  0x7EA98B20 0 154 n/a 0 154 SYSHISTOGRAMTEMPLA SYSIBM  0x7EA9A820 0 155 n/a 0 155 SYSHISTOGRAMTEMPLA SYSIBM  0x7EAA1420 0 157 n/a 0 157 SYSAUDITPOLICIES SYSIBM  0x7EF2AEA0 0 -1 n/a 0 -1 INTERNAL SYSIBM  0x7EAF3CA0 3 -1 n/a 3 -1 INTERNAL SYSIBM  TCB Table Stats:  Address TableName Scans UDI RTSUDI PgReorgs  0x7EF2AAA0 SYSBOOT 1 0 0 0  0x7EAAD4A0 SYSTABLES 0 713 713 0  0x7EAF1920 SYSINDEXES 0 309 309 0  0x7EAF38A0 TEST1 2 0 0 0  0x7EAF41A0 TEST2 1 0 0 0  0x7EAABBA0 SYSPLAN 0 2 2 0  0x7EAA5320 SYSDBAUTH 0 0 0 0  0x7EF2B4A0 SYSROUTINES 0 8 8 0  0x7EAA8BA0 SYSEVENTMONITORS 0 0 0 0  0x7EAA2AA0 SYSTABLESPACES 0 0 0 0  0x7EA918A0 SYSVERSIONS 1 0 0 0  0x7EF2FC20 SYSXMLSTRINGS 0 0 0 0  0x7EA90AA0 SYSXMLPATHS 0 0 0 0  0x7EAA7E20 SYSTASKS 0 0 0 0  0x7EAA02A0 SYSSURROGATEAUTHID 0 0 0 0  0x7EF2EB20 SYSROLES 0 0 0 0  0x7EAA3EA0 SYSROLEAUTH 0 0 0 0  0x7EA9D620 SYSCONTEXTS 0 0 0 0  0x7EA9F5A0 SYSCONTEXTATTRIBUT 0 0 0 0  0x7EAF02A0 SYSCOLLATIONS 0 0 0 0  0x7EA92420 SYSWORKLOADS 0 0 0 0  0x7EA93C20 SYSWORKLOADCONNATT 0 0 0 0  0x7EA94CA0 SYSWORKLOADAUTH 0 0 0 0  0x7EA99620 SYSSERVICECLASSES 1 0 0 0  0x7EA9C220 SYSWORKACTIONSETS 1 0 0 0  0x7EA96220 SYSTHRESHOLDS 1 0 0 0  0x7EA978A0 SYSHISTOGRAMTEMPLA 0 0 0 0  0x7EA98B20 SYSHISTOGRAMTEMPLA 0 0 0 0  0x7EA9A820 SYSHISTOGRAMTEMPLA 0 0 0 0  0x7EAA1420 SYSAUDITPOLICIES 0 0 0 0  0x7EF2AEA0 INTERNAL 0 0 0 0  0x7EAF3CA0 INTERNAL 0 0 0 0

命令成功完成。部分输出结果如清单 8 所示,想查看都有哪些表发生了表扫描可以看输出结果中“ TCB Table Information ”部分,其 “ TableName ”部分显示了发生过全表扫的表的名字。如果想查看全表扫发生的次数,可以查看“ TCB Table Stats ” 部分。





回页首

强行中断用户连接方法

我们在维护数据库的过程中,经常需要断开所有的用户连接,通常我们使用“ FORCE APPLICATIONS ALL ”命令,但是,这个命令并不能解决我们的所有问题。比如,当前有用户不停试图连接上来时,通过“ FORE APPLICATIONS ALL ”命令,就不能断开在命令发出之后试图连接上来的应用程序。

面对这个问题,如果 B/S 的程序,一般情况下需要先关闭应用服务器,比如 WAS ( Websphere Admin Server ),再在 DB2 服务器上多次运行“ FORCE APPLICATIONS ALL ”命令,以便断开所有的连接,这种方式不太容易断开其他绕过应用服务器试图直接连接数据库的应用程序。

如果想彻底断开所有的连接,可以考虑只开放给用户一个数据库别名,而不是把数据库名直接提供给客户。比如,我们现在服务器上有示例数据库 SAMPLE ,我们通过 CATALOG 命令给示例数据库 SAMPLE 定义一个别名,别名为 ABC ,然后将别名提供给用户。当我们需要断开所有连接的时候,我们先停掉应用服务器,比如 WAS ,然后在 DB2 服务器上多次运行“ FORE APPLICATIONS ALL ”命令,然后再通过 UNCATALOG 命令取消 SAMPLE 数据库的别名 ABC ,当我们单用户管理完成后,再将 SAMPLE 数据库的别名 ABC 恢复就可以了,关于注册别名和取消别名具体如清单 9 所示:


清单 9 . 编目数据库别名、取消编目数据库别名
/* 在 DB2 服务器上执行 */  C:/> db2 catalog db sample as abc  DB20000ICATALOG DATABASE 命令成功完成。 DB21056W 直到刷新目录高速缓存之后,目录更改才生效。 C:/> db2 terminate  DB20000ITERMINATE 命令成功完成。 /* 对用户只开放数据库别名 ABC,用户在在客户端上都使用 ABC 来编目 SAMPLE 数据库 */  C:/> DB2 catalog tcpip node myremoteremote123.124.78.115server50000  DB20000ICATALOG TCPIP NODE 命令成功完成。 DB21056W 直到刷新目录高速缓存之后,目录更改才生效。 C:/> db2 terminate  DB20000ITERMINATE 命令成功完成。 C:/> db2catalogdbabc as myabcatnodemyremote  DB20000ICATALOG DATABASE 命令成功完成。 DB21056W 直到刷新目录高速缓存之后,目录更改才生效。 C:/> db2 terminate  DB20000ITERMINATE 命令成功完成。 C:/> db2 connect to myabc user rhette using passw0rd 数据库连接信息数据库服务器 = DB2 / NT 9.1.0  SQL 授权标识 = RHETTE 本地数据库别名 = MYABC  /* 在 DB2 服务器上断开所有连接,取消别名 */  C:/> db2 force applications all  DB20000IFORCE APPLICATION 命令成功完成。 DB21024I 此命令为异步的,可能未能立即生效。 C:/> db2 uncatalog db abc  DB20000IUNCATALOG DATABASE 命令成功完成。 DB21056W 直到刷新目录高速缓存之后,目录更改才生效。 C:/> db2 terminate  DB20000ITERMINATE 命令成功完成。 /* 此时在客户端试图连接数据库 ABC,将会失败 */  C:/> db2 connect to myabc user rhette using passw0rd  SQL30061N 在远程节点上找不到数据库别名或数据库名称 " ABC" 。 SQLSTATE = 08004  /* 在 DB2 服务器上执行完单用户操作后,可以再把别名 ABC 恢复 */  C:/> db2 catalog db sample as abc  DB20000ICATALOG DATABASE 命令成功完成。 DB21056W 直到刷新目录高速缓存之后,目录更改才生效。 C:/> db2 terminate  DB20000ITERMINATE 命令成功完成。 /* 此时再在客户端连接数据库 ABC(在本地别名 MYABC),就可以成功了 */  C:/> db2 connect to myabc user rhette using passw0rd 数据库连接信息数据库服务器 = DB2 / NT 9.1.0  SQL 授权标识 = RHETTE 本地数据库别名 = MYABC





回页首

通过结果集创建表

如果你想通过结果集创建表,可以使用“ create table as ( select * from table_name )definition only ”语句。

下面我们新打开一个 DB2CLP 窗口,发出“ CONNECT TO SAMPLE ”命令,连上示例数据库 SAMPLE ,再发出“ create table newtest1 as ( select * from test1 ) definition only ”命令创建表 newtest1 ,其结构和 test1 完全相同,具体如清单 10 所示:


清单 10 . 通过结果集创建表
C:/> db2 connect to sample 数据库连接信息数据库服务器 = DB2 / NT 9.1.0  SQL 授权标识 = RHETTE 本地数据库别名 = SAMPLE  C:/> db2 create table newtest1 as ( select * from test1 ) definition only  DB20000ISQL 命令成功完成。 C:/> db2 select * from test1  ID  - - - - - - - - - - - - - - - - - - -  1  1  1  1  1  5 条记录已选择。 C:/> db2 select * from newtest1  ID  - - - - - - - - - - - - - - - - - - -  0 条记录已选择。

命令成功完成。





回页首

单引号转换

我们在使用 DB2 数据库的时候,不能直接插入单引号,而是要用两个单引号代表一个单引号,也就是需要进行转译。比如我们在插入 TEST2 表时,想对 NAME 列中插入带单引号的值,可以使用两个单引号代表一个单引号,具体如清单 11 所示:


清单 11. 单引号转换
C:/>db2 insert into test2 values ( 11 , ''' 单引 ''' , ' ' )  DB20000ISQL 命令成功完成。 C:/> db2 selectid ,name from test2  IDNAME  - - - - - - - - - - - - - - - - - - - - -  1  rhette  2        daniel  3  richard  4        henry  5  vivian  11  ' 单引 '  6 条记录已选择。

命令成功完成。在清单 11 中我们看到,为了插入 NAME 列 ' 单引 ' 字符串,在 INSERT 语句中使用了 '' 单引 '' 字符串进行替代,查询表 TEST2,可以看到插入的值为 ' 单引 ' 。





回页首

DB2 备份历史文件损坏

在维护 DB2 数据库,进行数据库备份操作时,我们偶尔会遇上错误代码为 SQL2048 错误,错误码为 5 。通过在 DB2CLP 窗口发出命令 “ db2 ? SQL2048 ” 查询错误代码为 SQL2048 (错误码为 5 )代表的含义,可以发现备份历史文件 db2rhist.asc 损坏(本示例假定实例所有者可访问 db2rhist 文件),具体如清单 12 所示:


清单 12. 查询错误代码为 SQL2048(错误码为 5)代表的含义
C:/> db2 ? SQL2048  SQL2048N 访问对象 "< 对象 >" 时出错。原因码:"< 原因码 >" 。说明 : 数据库实用程序的处理期间,在访问对象时出错。下面是原因码列表: 1 遇到无效对象类型。 2 锁定对象操作失败。锁定等待可能已达到数据库配置中指定的锁定超时限制。 3 数据库实用程序的处理期间,解锁对象操作失败。 4 访问对象失败。5数据库中的对象已毁坏。 . . . . . . . . . . . . . 实用程序停止了处理过程。用户响应 :  1 确保 "< 对象 >" 属于有效类型。 2 增大数据库配置参数 locktimeout 。 3 请检查在锁定 "< 对象 >" 时没有任何问题,然后再次尝试执行该操作。 4 和 7 请检查 "< 对象 >" 确实存在并且可访问。确保您具有访问它的正确特权 / 许可权。 5 如果对象是db2rhist.asc,那么确保实例所有者可访问db2rhist文件。如果正确设置了许可权,那么说明db2rhist文件可能已被破坏。将现有文件从它的现有位置移开,或者删除该文件。当DB2下一次需要访问db2rhist文件时,DB2将创建新的db2rhist文件。注意:删除db2rhist文件将导致丢失db2rhist文件中的历史信息。如果"<对象>"是任何其他数据库控制文件,那么可能需要恢复数据库。 . . . . . . . . . . . . .

遇到这种错误,可以参照下列步骤进行解决:

  1. 进入到 NODE000x/SQL000x 目录下,找到该文件 db2rhist.asc 文件以及其备份文件 db2rhist.bak,然后把 db2rhist.asc 文件移动到其他目录中。
  2. 重新执行数据库备份命令,在执行过程中,DB2 仍然会报错,不过会自动用 db2rhist.bak 文件来生成 db2rhist.asc 文件,当然前提是之前的错误只是由于 db2rhist.asc 文件损坏引起的,而 db2rhist.bak 文件没有损坏。
  3. 再次执行数据库备份命令,就可以备份成功了。

如果按照上述步骤执行后,还报这个错误,则可能是因为 db2rhist.bak 文件也损坏了,此时我们可以重新执行上面的三步操作,只是在第一步的时候,在挪走 db2rhist.asc 文件的同时把 db2rhist.bak 文件也挪走。这样,在执行第二步的时候,DB2 会自动生成 db2rhist.asc 文件和 db2rhist.bak 文件。





回页首

编译 SQL 语句时出现 SQL0101N 错误

我们在编译 SQL 语句,特别是复杂的 SQL 语句时,如果调用多个表或触发多个触发器,可能会占用大量的系统资源,此时,如果资源不够,可能会报错误代码为 SQL0101N 的错误。

遇到这样的错误,我们首先还是在 DB2CLP 窗口中,查询错误代码为 SQL0101N 的错误号的帮助信息,具体如清单 13 所示:


清单 13 . 查询错误代码为 SQL0101N 代表的含义
C:/> db2 ? SQL0101N  SQL0101N 语句太长或者太复杂。说明 : 因为超过长度或复杂度方面的系统限制,或因为涉及到太多的约束或触发器,所以不能处理该语句。如果该语句是创建或修改压缩描述的语句,那么新的压缩描述对系统目录中相应的列而言可能太大。联合系统用户还应检查该语句是否: * 超过对长度或复杂性的联合服务器系统限制或数据源系统限制。 * 违反其他某些特定于数据源的限制。不能处理该语句。注 : 在对运行于不同代码页下的应用程序和数据库执行字符数据转换时,转换的结果超过长度限制。用户响应 : 执行下列任意一项操作: * 将该语句分成为更短或简单些的 SQL 语句。 * 增大数据库配置文件中语句堆(stmtheap)的大小。 * 减少语句中涉及的检查或引用约束的数量,或者减少外键的索引数量。 * 减少该语句中涉及的触发器数。 * 联合系统用户:请确定哪个数据源使该语句失败(请参阅《故障诊断指南》以了解标识失败的数据源所要遵循的过程),并确定拒绝的原因。如果拒绝来自联合服务器,那么在数据库配置文件中增大语句堆(stmtheap)的大小。 sqlcode:-101  sqlstate:54001

如清单 13 所提供的提示,这是由于语句太长或者太复杂引起的,我们首先应该确认一下系统中没有递归的触发器存在(如果有的话,要取消这样的触发器),然后可以考虑修改以下数据库配置参数来解决这个问题:

  1. 增大数据库配置文件中语句堆( stmtheap )的大小。
  2. APPLHEAPSZ 缺省应用程序堆( application heap4KB )。
  3. PCKCACHESZ 程序包高速缓存大小( package cache4KB )。




回页首

恢复已删除的表 (Dropped Table Recovery)

我们在维护 DB2 数据库的过程中,偶尔会发生误删除表( DROP TABLE )的操作,这种误操作和删除表中的数据不一样。误删除数据,对于归档日志管理模式的数据库来说,可以通过前滚恢复来恢复数据,而误删除表则需要在前滚恢复的时候加上“ recover dropped table tableid to target_dir ”选项,具体的步骤如下:

  1. 确保数据库可以进行前滚恢复( DB2 V9 之前的版本要保证数据库配置参数 logretain 或 userexit 打开, DB2 V9 则除了打开 logretain 或 userexit 参数可以把数据库改成归档管理模式,还可以通过修改 logarchmeth1 数据库配置参数来更改日志管理模式)。注意,需要在误删除表操作发生之前,数据库已经处于归档日志管理模式状态。
  2. 确保要被恢复的表所在的表空间“允许已废弃的表可恢复”, 在 DB2 V9 之前版本的数据库中,仅限常规表空间( regular tablespace ),在 DB2 V9 的版本中,由于对大型表空间做了修改,已经用来替代 V9 之前版本的常规表空间,所以,大型表空间也可以“允许已废弃的表可恢复”。如果误删除的表所在的表空间没有启用“允许已废弃的表可恢复”功能,可以通过命令启用这个功能:
    ALTER TABLESPACE表空间名DROPPED TABLE RECOVERY ON
    也可以通过在控制中心使用图形化的方式进行修改,如图 3 所示:

    图 3. 修改表空间属性,启用“允许已废弃的表可恢复”功能
     
  3. 通过发出 “ list history dropped table all for 数据库名”命令,得到被删除表的 tableid 和表结构的 DDL 语句。记录下 tableid 和 DDL 语句,以便我们在第四步操作以及以后的恢复操作中使用。
  4. 利用误删除操作发生之前的数据库全备恢复数据库。
  5. 前滚数据库,在前滚时加上“ recover dropped table tableid to target_dir ”选项,其中 tableid 是第三步中得到的 tableid , target_dir 表示目的目录(在此目录中,将会创建 ../NODE000X/data 文件)用来存放误删除表中的数据。
  6. 利用第三步得到的 DDL 语句创建误删除的表,并将第五步中 target_dir 目录中的文件导入数据到表中。

下面我们通过具体的例子来看一下如何恢复已经删除的表。

首先我们需要把示例数据库 SAMPLE 的日志模式改成归档模式。下面在 DB2CLP 窗口中,先发出“ CONNECT TO SAMPLE ”命令,连上示例数据库 SAMPLE ,再发出“ UPDATE DATABASE CONFIGURATION USING LOGARCHMETH1 DISK:C:/DB2/IMMEDIATE ”命令,修改数据库配置参数 LOGARCHMETH1 ,使其自动归档日志到 C 盘 DB2 目录下,具体如清单 14 所示:


清单 14 . 修改示例数据库 SAMPLE 的配置参数
C:/> db2 connect to sample 数据库连接信息数据库服务器 = DB2 / NT 9.1.0  SQL 授权标识 = RHETTE 本地数据库别名 = SAMPLE  C:/> DB2 UPDATE DATABASE CONFIGURATION USING LOGARCHMETH1 DISK:C:/DB2/IMMEDIATE  DB20000IUPDATE DATABASE CONFIGURATION 命令成功完成。 SQL1363W 未动态更改为立即修改而提交的一个或多个参数。对于这些配置参数,必须在所有应用程序都与此数据库断开连接之后,更改才会生效。

命令执行成功,这样我们就把示例数据库 SAMPLE 的日志模式改成了归档。在清单 14 中的命令执行成功后,由于 LOGARCHMETH1 配置参数更改成功后,需要等数据库上所有的连接都断开后才会生效,所以我们在 DB2CLP 窗口中,发出“ FORCE   APPLICATIONS ALL ”命令断开所有的连接,具体如清单 15 所示:


清单 15. 断开所有应用程序连接
C:/> DB2 FORCE APPLICATIONS ALL  DB20000IFORCE APPLICATION 命令成功完成。 DB21024I 该命令为异步的,可能不会立即生效。

命令成功后,用 LIST   APPLICATIONS 看所有应用程序是否都断开了,如果没有断开,再重复执行 FORCE APPLICATIONS ALL ,保证所有连接都断开后,把数据库做一次全备。在我们首次把数据库的日志模式由循环模式改成归档模式后,数据库会处于 BACKUP   PENDING 状态,强制我们进行一次全量备份,在全量备份完成之前,不能访问数据库或表空间。

下面我们继续在 DB2CLP 窗口中,发出“ BACKUP DB SAMPLE ”命令,全量备份示例数据库 SAMPLE ,具体如清单 16 所示:


清单 16 . 对示例数据库做一次全备
C:/> DB2 LIST   APPLICATIONS  DB21034E 该命令被当作 SQL 语句来处理,因为它是无效的“命令行处理器”命令。在 SQL 处理期间,它返回: SQL1224N 由于错误或强制中断,导致数据库管理器不能接受新请求,已终止正在处理的所有请求,或者已终止特定请求。 SQLSTATE = 55032  C:/> db2 backup db sample 备份成功。此备份映像的时间戳记是:20080405000129

备份成功完成,备份映像文件的时间戳记为 20080405000129 。

下面我们继续在当前 DB2CLP 窗口中,发出“ CONNECT TO SAMPLE ”命令,连上示例数据库 SAMPLE ,再发出“ db2 create table newtest2 ( id int , name varchar(10) ) ” 创建示例表 NEWTEST2 ,并插入 2 条记录,然后删除掉表 NEWTEST2 ,具体如清单 17 所示:


清单 17. 创建示例表 NEWTEST2,并删除掉
C:/> db2 connect to sample 数据库连接信息数据库服务器 = DB2 / NT 9.1.0  SQL 授权标识 = RHETTE 本地数据库别名 = SAMPLE  C:/> db2 create table newtest2 ( id int , name varchar(10) )  DB20000ISQL 命令成功完成。 C:/> db2 insert into newtest2values ( 1 ,'aa' )  DB20000ISQL 命令成功完成。 C:/> db2 insert into newtest2values ( 2 ,'bb' )  DB20000ISQL 命令成功完成。 C:/>db2 drop table newtest2  DB20000ISQL 命令成功完成。

命令成功完成。下面我们来把已经删除的表 NEWTEST2 恢复。参照本小节开头的步骤,第一步确保数据库已经处于归档管理模式已经完成,第二步,确保误删除表所在的表空间启用了“允许已废弃的表可恢复”也已经完成( IBMDB2SAMPLEREL 默认已经启用“允许已废弃的表可恢复”功能),具体如图 4 所示:


图 4. 查看 IBMDB2SAMPLEREL 是否启用“允许已废弃的表可恢复”功能
 

下面我们来进行第三步的操作。继续在当前 DB2CLP 窗口中,通过发出 “ list history dropped table all for 数据库名”命令,得到被删除表 NEWTEST2 的 tableid 为“ 000000000000cdd200030020 ”和表结构的 DDL 语句。记录下 tableid 和 DDL 语句,以便我们在第四步操作以及以后的恢复操作中使用。具体如清单 18 所示:


清单 18 . 第三步,得到被删除表 NEWTEST2 的 tableid 和表结构的 DDL 语句
C:/> db2 list history dropped table all for sample 列示 sample 的历史记录文件匹配的文件条目数 = 1  Op 对象 时间戳记 + 序列类型 设备 最早日志当前日志备份标识 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  D T 20080405002004000000000000cdd200030020  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  "RHETTE"."NEWTEST2" 驻留在 1 表空间中: 00001 IBMDB2SAMPLEREL  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 注释:DROP TABLE 开始时间:20080405002004 结束时间:20080405002004 状态:A  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  EID:95  DDL: CREATE TABLE "RHETTE"."NEWTEST2" ( "ID" INTEGER , "NAME" VARCHAR(10) )  IN "IBMDB2SAMPLEREL" ;  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

下面我来做第四步。

利用之前清单 16 所在数据库全备生成的备份映像文件(时间戳记为 20080405000129 ) 恢复示例数据库 SAMPLE 。我们继续在当前 DB2CLP 窗口,发出“ FORCE APPLICATIONS ALL ”命令,停掉示例数据库 SAMPLE 上所有的连接,再发出“ db2 restore db sample taken at 20080405000129 ”命令恢复数据库,还原的过程中,会提示“ SQL2539W 警告!正在复原至与备份映像数据库相同的现有数据库。数据库文件将被删除。想要继续吗?( y / n )”,这时候输入 “ y ”,也就是“是”的意思,回车。具体如清单 19 所示:


清单 19. 第四步,恢复示例数据库 SAMPLE
C:/> db2 force applications all  DB20000IFORCE APPLICATION 命令成功完成。 DB21024I 此命令为异步的,可能未能立即生效。 C:/> db2 restore db sample taken at 20080405000129  SQL2539W 警告!正在复原至与备份映像数据库相同的现有数据库。数据库文件将被删除。想要继续吗?( y / n ) y  DB20000IRESTORE DATABASE 命令成功完成。

命令成功完成。

下面我们继续来做第五步,前滚数据库。

继续在当前 DB2CLP 窗口中,利用第三步得到的 tableid ( 000000000000cdd200030020 )发出前滚恢复命令“ db2 rollforward db sample to end of logs and stop recover dropped table 000000000000cdd200030020 to c:/db2 ”,具体如清单 20 所示:


清单 20. 第五步,前滚恢复示例数据库 SAMPLE
C:/> db2 rollforward db sample to end of logs and stop recover dropped             table 000000000000cdd200030020 to c:/db2 前滚状态输入数据库别名 = sample 节点数已返回状态 = 1 节点号 = 0 前滚状态 = 未暂挂下一个要读取的日志文件 = 已处理的日志文件 = S0000000.LOG - S0000000.LOG 上次落实的事务 = 2008-04-04-16.37.26.000000 UTC  DB20000IROLLFORWARD 命令成功完成。

命令成功完成。误删除表 NEWTEST2 的数据被导入到了 C:/DB2/NODE0000/data 文件中。

下面我们来进行第六步,也是最后一步。

继续在当前 DB2CLP 窗口中,发出“ CONNECT TO SAMPLE ”命令,连上示例数据库 SAMPLE ,再利用第三步得到的表 NEWTEST2 的 DDL 语句重新创建表 NEWTEST2 ,再从 C:/DB2/NODE0000/data 文件导入数据,具体如清单 21 所示:


清单 21. 第六步,重新创建表 NEWTEST2,再从 ../NODE0000/data 文件导入数据
C:/> db2 connect to sample 数据库连接信息数据库服务器 = DB2/NT 9.1.0  SQL 授权标识 = RHETTE 本地数据库别名 = SAMPLE  C:/> db2CREATE TABLE "RHETTE"."NEWTEST2" ( "ID" INTEGER , "NAME" VARCHAR(10) )             IN "IBMDB2SAMPLEREL"  DB20000ISQL 命令成功完成。 C:/> db2 import from C:/DB2/NODE0000/data of del insert into newtest2  SQL3109N 实用程序正在开始从文件 "C:/DB2/NODE0000/data" 装入数据。 SQL3110N 实用程序已完成处理。从输入文件读了 " 2 " 行。 SQL3221W. . . 开始 COMMIT WORK 。输入记录计数 = " 2 " 。 SQL3222W. . . 对任何数据库更改的 COMMIT 都成功。 SQL3019N 处理了输入文件中的 " 2 " 行。已将 " 2 " 行成功插入表中。拒绝了 " 0 " 行。读取行数 = 2 跳过行数 = 0 插入行数 = 2 更新行数 = 0 拒绝行数 = 0 落实行数 = 2  C:/> db2 select * from newtest2  IDNAME  - - - - - - - - - - - - - - - - - - - - -  1        aa  2        bb  2 条记录已选择。

命令成功完成。至此,我们已经完成了六步全部操作,被误删除的表 NEWTEST2 已经成功的恢复,数据也成功的导入其中。

需要注意的是,对可从已废弃的表中复原的数据类型有一些限制,下列类型不可能复原:

  1. 大对象( LOB )或长型字段数据。对于大型表空间,不支持 DROPPED TABLE RECOVERY 选项。如果尝试复原包含 LOB 或 LONG VARCHAR 列的已废弃的表,这些列将在生成的导出文件中设置为 NULL 。仅可对常规表空间使用 DROPPED TABLE RECOVERY 选项,而不能对临时或大型表空间使用。
  2. 与行类型相关的元数据。(数据已复原,但不是元数据。)将复原有类型表的层次结构表中的数据。此数据包含的信息可能比已废弃的类型表中的信息多。
  3. XML 数据。如果尝试恢复包含 XML 数据的已废弃的表,那么相应的列数据将为空。
原创粉丝点击