数据库日志

数据库日志

 

DB2 数据库支持两种不同的日志模式:循环(Circular归档(Archival。当新数据库创建时,系统默认的日志模式为循环。如果业务需求要求更高级的功能,您可以将日志模式从循环修改为归档。

DB2 事务日志摘要

事务是逻辑工作单元。每一个事务在事务日记文件中都存储有相应的日志记录。每个事务都有一个相应的 Redo Log 条目。Redo Log 条目将写入当前的活动日志文件。当活动日志文件变满时,它将被标记为 unavailable。此时,DB2 将接着此活动日志文件另外创建一个日志文件,并继续在其中写入日志条目。当前活动日志文件变满时,DB2 将重复这一循环过程。当事务完成后(发起 COMMIT ROLLBACK 语句),相应的日志条目将被释放,因为不再需要将它们用于恢复数据库。

DB2 将一直尝试将日志条目写入主要日志文件集,也就是数据库活动时间自动分配的日志文件。如果某个事务将所有主要日志文件消耗怠尽(所有主要日志文件都被标记为 unavailable),则数据库管理员将分配一个次要日志文件。当这个文件变满时,数据库管理员将再次检查主要日志文件的状态是否为 unavailable。如果是,则再分配一个次要日志文件并继续在其中写入条目。该过程将不断重复,直到所有次要日志文件都分配并写满。如果没有主要日志文件可供写入 Redo 条目,并且已经分配最大数量的次要日志文件,则应用程序将收到以下错误消息:

SQL0964C The transaction log for the database is full.

希望您曾经遇到过这种错误。但是,如果遇到此错误,则应该根据需要增加主要和次要日志文件(或者它们的大小)的数量。在理想情况下,主要日志文件的数量或大小应该足够保存最大的事务。分配次要日志文件相当消耗资源,因为它将在运行时执行。因此,我们应该将需要在高峰工作负荷期间分配的次要日志文件数量降到最低。要更新主要或次要日志文件的数量,可以发起以下命令:

  • UPDATE DB CFG FOR db_name USING LOGPRIMARY value
  • UPDATE DB CFG FOR db_name USING LOGSECOND value

注意:如果出现此问题,则应该分析造成整个日志文件空间变满的原因是什么。它可能是由失控查询或用户错误造成的,因此增加日志文件的数量或大小只能在表面上解决问题。比如说,假设某个用户发起了一个 DELETE FROM tab1 语句,且 TAB1 是一个相当大的表。虽然这一语句看上去没什么问题,每行生成一条删除日记记录,但是如果未经过配置处理它可以轻易地将日志空间填满。

 

循环日志

当循环日志生效时,事务数据将通过循环的方式写入主要日志文件。当存储于某个日志文件中的所有记录都不再需要用于恢复时,该日志文件将被重用,并且可以在以后再次成为活动日志文件。这意味着在循环日志模式中,日志文件的内容最终将被新日志条目重写。由于日志文件的内容被重写覆盖了,因此我们只能将数据库恢复到最后一次完整的数据库备份。不能使用循环日志执行时间点(point-in-time)恢复。

 

归档日志

在归档日志模式中,redo log 条目将写入主要日志文件。但是,与循环日志不同,这些日志文件永远都不可重用。当存储于某个日志文件中的所有记录都不再需要用于恢复时,该日志文件将被标记为非活动 而不是可重用。这意味着它的内容永远都不会被覆盖。当第一个主要日志文件变满时,系统将分配一个新的日志文件,这样主要日志文件的配置数量(LOGPRIMARY 数据库参数)将一直可用。

与单个事务相关的所有条目必须在活动日志空间中保持一致。如果长时间运行的事务所需要的日志空间大于主要日志文件可以提供的空间,则可能会分配并使用次要日志文件。在归档日志模式中,通过结合使用数据库备份映像和日志文件,我们可以将数据库恢复到具体的时间点。有关此流程的详细描述请参见下文。

 

如何修改日志模式

创建新的 DB2 数据库时,默认的日志模式为循环日志 。如果希望将日志模式从循环修改为归档,可以执行以下步骤:

<!--[if !supportLists]-->1.     <!--[endif]-->在磁盘上创建一个文件夹(比如说 e:\db_name\archive),磁盘上必须有足够的空间存储归档日志文件。保证归档文件目标文件夹与活动日志文件目标文件夹分开。

<!--[if !supportLists]-->2.     <!--[endif]-->终止与数据库的连接:

<!--[if !supportLists]-->o    <!--[endif]-->TERMINATE
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->3.     <!--[endif]-->更新归档日志文件目标文件夹(为归档日志文件指定路径可以将归档日志模式打开)。

<!--[if !supportLists]-->o    <!--[endif]-->UPDATE DB CFG FOR db_name USING LOGARCHMETH1 "Disk:e:\db_name\archive"
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->4.     <!--[endif]-->重新连接到数据库:

<!--[if !supportLists]-->o    <!--[endif]-->CONNECT TO db_name
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->5.     <!--[endif]-->连接失败并显示以下错误消息:

SQL1116N A connection to or activation of database db_name cannot be made because of backup pending: SQLSTATE=57019

出现错误消息的原因是,日志模式已经从循环更改为归档,并且需要执行完全数据库备份。数据库处于循环日志模式时执行的备份并不充分,因此当切换模式后需要执行新备份。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->6.     <!--[endif]-->使用以下命令执行完全数据库备份:

<!--[if !supportLists]-->o    <!--[endif]-->BACKUP DATABASE db_name TO d:\db_name\backup
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

<!--[if !supportLists]-->7.     <!--[endif]-->尝试再次连接到数据库。这次应该能够成功。

<!--[if !supportLists]-->o    <!--[endif]-->CONNECT TO db_name

保护数据安全的最佳实践

要保证数据的安全,可以使用以下最佳实践:

<!--[if !supportLists]-->1.     <!--[endif]-->保证数据库处于归档日志模式,这样当数据库发生故障时便可以将它恢复到特定的时间点。

<!--[if !supportLists]-->2.     <!--[endif]-->定期执行完整和递增的数据库备份。业务需求将最终决定时间表和频率。

<!--[if !supportLists]-->3.     <!--[endif]-->对于任务关键型数据库,准备一个副本或备用数据库以供随时使用。

<!--[if !supportLists]-->4.     <!--[endif]-->将活动日志文件和归档日志文件保存在不同的位置,并且各位置拥有充分的磁盘空间。

<!--[if !supportLists]-->5.     <!--[endif]-->确保使用以下命令将数据库参数 BLK_LOG_DSK_FUL 设置为值 YES

<!--[if !supportLists]-->o    <!--[endif]-->UPDATE DB CFG FOR db_name USING BLK_LOG_DSK_FUL YES

BLK_LOG_DSK_FUL 设置为 YES 后,如果 DB2 遇到错误(因为保存日志文件的文件系统变满)则会导致应用程序挂起。这样将允许我们解决错误,并允许完成运行中的事务。要解决日志磁盘空间不足错误,可以将原来的日志文件移动到另一个文件系统,或者扩大文件系统的空间。

恢复场景

理解故障出现的原因以及如何从故障中恢复是非常重要的。以下部分将模拟各种不同的故障类型,并介绍如何从故障中恢复系统。

场景 1. 整个数据库意外删除和损坏

本场景将展示如何从完全数据库故障中恢复。遇到这种情况的原因可以是数据库意外删除或受到破坏,也可以是人为错误或硬件故障造成的不一致性。在这些情况中,可以通过应用上次完全数据库备份对数据库进行恢复。该场景基于 1 中的配置。


1. 恢复场景中所使用的配置

组件

描述

操作系统

Windows XP Service Pack 2 / RHEL 4.0

DB2 版本和等级

DB2 UDB Enterprise Server Edition (ESE) V8.2.6 fixpak 13 / DB2 V9.1 ESE fixpak 1

数据库名称

TESTDB1

 

步骤 1. 执行完全数据库备份

要执行完全脱机数据库备份,可以使用以下命令:

  • TERMINATE
  • FORCE APPLICATION ALL
  • BACKUP DATABASE testdb1 TO c:\testdb1\backup

需要注意备份文件名称中生成的 ID。它类似于:20060411154219。这个 ID 只是备份映像的时间戳,恢复过程中需要使用它。

步骤 2. 模拟故障

要模拟故障场景,可以完全删除数据库:

  • TERMINATE
  • FORCE APPLICATION ALL
  • DROP DATABASE testdb1

现在,尝试连接数据库:

  • CONNECT TO testdb1

将报告以下错误,它提示找不到此数据库:

Error: SQL1013N Database alias name or Database name "testdb1" could not found.

步骤 3. 创建一个新的数据库

要开始恢复过程,首先创建一个与丢弃数据库名称相同的数据库:

  • CREATE DATABASE testdb1

查看数据库目录的内容,确保数据库创建成功且目录正确:

  • LIST DB DIRECTORY

步骤 4. 恢复数据库

恢复数据库备份映像。在本例中,我使用时间戳 20060411154219 恢复备份映像:

  • RESTORE DATABASE testdb1 FROM c:\testdb1\backup TAKEN AT 20060411154219 INTO testdb1

将返回以下报警消息

SQL2523W: Restoring to an existing database that is different from the database on the backup image. The target database will be overwritten by the backup version. The roll-forward recovery logs associated with the target database will be overwritten.

Y 键继续运行。该操作将把数据库备份恢复到前一步骤中创建的数据库。成功恢复映像之后,数据库将与备份时的数据库完全一致。

步骤 5. 连接到数据库

尝试连接到数据库:

  • CONNECT TO testdb1

可能会返回以下错误消息:

SQL1117N A connection to or activation of database "testdb1" cannot be made because of Roll-Forward Pending SQLSTATE=57019.

出现错误的原因可能是,必须使用某些日志文件进行一致性检查。使用以下命令将数据库恢复到一致状态:

  • ROLLFORWARD DATABASE testdb1 COMPLETE

再次尝试连接到数据库:

  • CONNECT TO testdb1

步骤 6. 数据库和对象验证

验证之前的对象仍然存在且可用,比如说:

<!--[if !supportLists]-->o    <!--[endif]-->LIST TABLESPACES SHOW DETAIL

<!--[if !supportLists]-->o    <!--[endif]-->LIST TABLES

上一条命令应该会提示,所有表空间均处于正常状态并且可以访问容器。所有表及表中的数据集合应该与执行备份时的状态一致。

 

场景 2. 表空间容器意外丢弃或损坏的表空间容器

本场景将展示当一个或多个表空间容器丢失或损坏时如何恢复数据库系统。出现此情况的原因可以是人为错误(比如说,某个用户删除了某个目录或文件)或数据文件损坏问题。本场景基于 2 中的配置。


2. 场景 2 中所使用的系统配置

组件

描述

操作系统

Windows XP Service Pack 2 / RHEL 4.0

DB2 版本和等级

DB2 UDB Enterprise Server Edition (ESE) V8.2.6 fixpak 13 / DB2 V9.1 ESE fixpak 1

数据库名称

TESTDB1

表空间名称

TS1

TS1 中的容器

c1.dat, c2.dat, c3.dat, c4.dat

 

步骤 1. 获取定义的所有表空间的目录

  • CONNECT TO testdb1
  • LIST TABLESPACES SHOW DETAIL

步骤 2. 获取所有表空间容器信息的目录

  • LIST TABLESPACE CONTAINERS FOR 1 SHOW DETAIL

注意:上面命令中的 “1” 是本环境中表空间 TS1 的表空间 ID。它是通过之前 LIST TABLESPACES SHOW DETAIL 命令中的输出获得的。所使用的每个表空间 ID 都需要重复这个命令。

步骤 3. 备份表空间

  • TERMINATE
  • FORCE APPLICATION ALL
  • BACKUP DATABASE testdb1 TABLESPACE ts1 TO c:\testdb1\backup\ts1

如您所见。本场景假定用户对大多数重要的表空间都执行了备份(供恢复使用)。

步骤 4. 模拟表空间故障

手动模拟此场景,即表空间容器文件被某个用户意外删除:

  • DEL C:\TESTDB1\TS1\C1.DAT
  • DEL C:\TESTDB1\TS1\C2.DAT
  • DEL C:\TESTDB1\TS1\C3.DAT

随后,当我们连接到数据库并尝试执行与表空间 TS1 相关的操作时,将返回错误。比如说:

  • CONNECT TO testdb1
  • CREATE TABLE tab1(c1 INTEGER) IN ts1

返回以下错误消息:

SQL0290N Table space access is not allowed.

还可以使用以下命令检查表空间状态:

<!--[if !supportLists]-->o    <!--[endif]-->LIST TABLESPACES SHOW DETAIL

删除容器后,上面的命令将显示 TS1 的状态为 0x400 ,该代码表示脱机且不可访问状态。由于删除了三个容器,因此表空间不再处于正常状态(0x000)。

如果再次执行 LIST TABLESPACE CONTAINERS 命令,可以验证哪些容器丢失或不可用:

  • LIST TABLESPACE CONTAINERS FOR 1 SHOW DETAIL

在结果中,容器 C1C2 C3 Accessible 状态将显示为 No

步骤 6. 恢复表空间备份映像

要恢复备份映像,可以使用以下命令:

  • TERMINATE
  • RESTORE DATABASE testdb1 TABLESPACE (ts1) FROM C:\TESTDB1\BACKUP\TS1

步骤 7. 检查表空间状态

确保容器可以访问:

  • LIST TABLESPACES SHOW DETAIL
  • LIST TABLESPACE CONTAINERS FOR 1 SHOW DETAIL

如果恢复成功,表空间 TS1 的状态应该为正常(0x000)并且所有容器应该都可以访问。

步骤 8. 验证恢复是否成功

  • CREATE TABLE tab1(no INTEGER) IN ts1

注意:您可能会遇到以下这种情况:恢复表空间之后仍然需要进一步恢复操作。如果有任何日志文件修改未被应用(以确保数据库的一致性),都有可能出现这种情况。在这种情况下,使用以下任一命令完成恢复:

  • ROLLFORWARD DATABASE testdb1 COMPLETE

OR

  • ROLLFORWARD DATABASE testdb1 TO END OF LOGS AND STOP

以上命令将应用所有剩余的日志文件,从而将数据库恢复到一致状态。

 

场景 3. 某个表意外丢失

对于含有上千个表的数据库环境,难免会错误地丢弃某个表。在本场景中,您将看到如何恢复意外丢弃的表。要执行这种类型的恢复,必须将数据库配置为归档日志模式,并且可以使用完全数据库备份映像。要对丢弃的表执行恢复操作,表所在的表空间必须将 DROPPED TABLE RECOVERY 选项打开。可以在创建表空间的过程中设置此选项,也可以直接调用 ALTER TABLESPACE 语句。DROPPED TABLE RECOVERY 选项特定于表空间且局限于常规表空间。

本场景基于 3 中的系统配置。


3. 场景 3 中所使用的系统配置

组件

描述

操作系统

Windows XP Service Pack 2 / RHEL 4.0

DB2 版本和等级

DB2 UDB Enterprise Server Edition (ESE) 8.2.6 fixpak 13 / DB2 9.1 ESE fixpak 1

数据库名称

TESTDB1

表空间名称

TS1

表名称

TAB1

 

步骤 1. 执行完全数据库备份

  • TERMINATE
  • FORCE APPLICATION ALL
  • BACKUP DATABASE testdb1 TO c:\testdb1\backup

需要注意备份映像的时间戳。

步骤 2. 连接到数据库并执行生成日志记录的操作

  • CONNECT TO testdb1
  • CREATE TABLE tab1(no INTEGER) IN ts1
  • TERMINATE
  • ARCHIVE LOG FOR DATABASE testdb1
  • CONNECT TO testdb1
  • INSERT INTO tab1 VALUES(1)
  • INSERT INTO tab1 VALUES(2)
  • INSERT INTO tab1 VALUES(3)
  • COMMIT
  • TERMINATE
  • ARCHIVE LOG FOR DATABASE testdb1
  • CONNECT TO testdb1
  • INSERT INTO tab1 VALUES(4)
  • INSERT INTO tab1 VALUES(5)
  • COMMIT
  • TERMINATE
  • ARCHIVE LOG FOR DATABASE testdb1
  • CONNECT TO testdb1
  • SELECT * FROM tab1 /* check the 5 committed values from TAB */

步骤 3. 模拟意外丢弃表的场景

  • DROP TABLE tab1
  • COMMIT
  • SELECT * FROM tab1

将返回以下错误消息:

Error: SQL0204N "Administrator.TAB1" is an undefined name

步骤 4. 恢复数据库

要恢复已被丢弃的表,先恢复数据库备份,然后执行向前恢复(rollforward)操作:

  • TERMINATE
  • FORCE APPLICATION ALL
  • RESTORE DATABASE testdb1 FROM c:\testdb1\backup TAKEN AT 20070314144204 INTO testdb1

将返回以下消息:

SQL2539W Warning! Restoring to an existing database that is the same as the Backup image database.
The database files will be deleted.

Do you want to continue? (Y/N)

Y 键完成此过程。

步骤 5. 检索已丢弃表的对象 ID

使用以下命令检索意外丢弃的表的对象 ID

  • LIST HISTORY DROPPED TABLE ALL FOR DATABASE testdb1

可以将返回的信息(比如说 清单 1 中显示的示例)复制到某个文本文件中以供未来引用。


清单 1. LIST HISTORY 命令返回的信息

                    
 
Op Obi Timestamp Sequence Type Dev Earliest Log Current Log  Backup ID
-- --- ------------------ ---- --- ------------ ------------ -----------------------------
 D  T  20070314142913                                                000000000000892700050108
------------------------------------------------------------------------------------------
 "ADMINISTRATOR"."TAB1" resides in 1 table space(s):
 00001 TS1
----------------------------------------------------------------------------
 Comment: DROP TABLE
 Start Time: 20070314142913
 End Time: 20070314142913
 Status: A
----------------------------------------------------------------------------
 EID: 37
 DDL: CREATE TABLE "ADMINISTRATOR"."TAB1" ( "NO" INTEGER )  IN "TS1" ;

 

清单 1 中的 Backup ID 栏显示被丢弃表的 ID 000000000000892700050108。这一信息对于恢复表非常重要。

步骤 6. 向前恢复数据库

现在已经获得了被丢弃表的 ID,下一步需要使用该表的备份 ID RB 数据库,这样才能够导入表的数据。在向前恢复数据库之前,需要确保有一个目录可供存储导入数据,比如说 c:\testdb1\exporttab1。使用以下命令向前恢复数据库:

  • ROLLFORWARD DATABASE testdb1 TO END OF LOGS
    AND STOP RECOVER DROPPED TABLE 000000000000892700050108 TO c:\testdb1\exporttab1

使用 END OF LOGS 选项的作用是让 DB2 在执行备份操作后应用所有可用日记文件。

步骤 7. 检查导入的数据文件

完成数据库向前恢复之后,需要检查在 ROLLFORWARD 命令中指定路径。应该能够找到一个 .TXT 文件,打开该文件并验证其中包含的数据与意外丢弃表之前的数据相同。

步骤 8. 连接到数据库并重新创建被丢弃的表

验证导出文件之后,我们需要重新创建被丢弃的表并重新填入数据。被丢弃表的定义包含在步骤 5 LIST HISTORY 命令的输出中。连接到数据库并执行 CREATE TABLE 语句:

  • CONNECT TO testdb1
  • CREATE TABLE "ADMINISTRATOR"."TAB1" ( "NO" INTEGER ) IN "TS1"

步骤 9. 导入数据

重新创建表之后,可以使用以下命令将数据库重新导入到表中:

  • IMPORT FROM c:\testdb1\exporttab1\Node0000\data.txt OF DEL INSERT INTO administrator.tab1

IMPORT 工具将导出文件中的所有数据导回到表中并在成功后发送报告(未显示)。

步骤 10. 验证恢复后的数据

确保 IMPORT 过程中没有错误或报警,并且所有数据都已导回表中:

  • SELECT * FROM tab1

如果一切运行正常,则意外丢弃点之前的所有数据应该都在表中。

 

场景 4. 恢复到时间点

如果某个表空间被丢弃或受到破坏,则定义在其中的表及数据将不可访问。要从此场景中恢复系统,需要一个可用的完全数据库备份映像并且需要将数据库配置为归档日志模式。本场景基于 4 中的系统配置。


4. 场景 4 中所使用的系统配置

组件

描述

操作系统

Windows XP Service Pack 2 / RHEL 4.0

DB2 版本和等级

DB2 UDB Enterprise Server Edition (ESE) 8.2.6 fixpak 13 / DB2 9.1 ESE fixpak 1

数据库名称

TESTDB1

表空间名称

TS1

表空间

TAB1

 

步骤 1. 执行完全数据库备份

  • TERMINATE
  • FORCE APPLICATION ALL
  • BACKUP DATABASE testdb1 TO c:\testdb1\backup

务必记录下备份映像文件接收到的时间戳,因为恢复过程需要使用它。

步骤 2. 创建一个新的表空间

创建一个新的表空间 TS1,以供本恢复场景使用:

  • CREATE TABLESPACE TS1 MANAGED BY DATABASE USING (FILE 'c:\testdb1\s4\C1.dat' 1000 )
    EXTENTSIZE 8 PREFETCHSIZE 24

确认表空间和相关容器都已创建:

  • LIST TABLESPACES
  • LIST TABLESPACE CONTAINERS FOR n SHOW DETAIL

其中,n LIST TABLESPACES 输出中显示的表空间 ID

步骤 3. 创建一个表并对它执行一些操作

创建表空间之后,创建一个名为 TAB1 的表并将它放到表空间中。在表中插入一些数据。为了让此场景更接近现实,使用一些命令强制 DB2 打开归档文件:

  • CREATE TABLE tab1 (no INTEGER) IN TS1
  • INSERT INTO tab1 VALUES(1)
  • INSERT INTO tab1 VALUES(2)
  • COMMIT
  • TERMINATE
  • ARCHIVE LOG FOR DATABASE testdb1
  • CONNECT TO testdb1
  • INSERT INTO tab1 VALUES(3)
  • INSERT INTO tab1 VALUES(4)
  • INSERT INTO tab1 VALUES(5)
  • COMMIT
  • SELECT * FROM tab1
  • TERMINATE
  • ARCHIVE LOG FOR DATABASE testdb1
  • CONNECT TO testdb1

步骤 4. 模拟表空间故障

要在此场景中模拟一个故障,需丢弃表空间:

  • DROP TABLESPACE ts1
  • SELECT * FROM tab1

将返回以下错误消息:

SQL0204N Error table does not exist "Administrator.Tab1" is an Undefined Name.

步骤 5. 恢复数据库

丢弃表空间之后,这个表空间的所有内容也被丢弃。要恢复表空间,恢复上一次可用备份映像:

  • TERMINATE
  • RESTORE DATABASE testdb1 FROM c:\testdb1\backup
    TAKEN AT 20070315150901
    INTO testdb1

在执行 RESTORE 命令时,需要使用在步骤 1 中记录的备份时间戳。将接收到以下报警消息:

SQL 2539W Warning! Restoring to an existing database that is same as the backup image database.
The database files will be deleted.

Do you want to continue? (Y/N)

Y 键继续执行。

步骤 6. 向前恢复数据库

恢复数据库之后,尝试连接到数据库:

  • CONNECT TO testdb1

将返回以下消息:

SQL 111N A connection to or activation of database cannot be made because of Roll-forward Pending. SQLSTATE=57019

RB 数据库之后,我们需要计算出丢弃表空间的时间戳。为此,使用 LIST HISTORY 命令:

  • LIST HISTORY CREATE TABLESPACE ALL FOR DATABASE testdb1

我们可以看到被丢弃表空间的准确时间戳。但是,不应该使用这个时间戳,因为需要使用在它之前的时间戳值恢复最近一次提交的值。

本示例将使用 20070315151500 作为时间戳来进行恢复。需要将该数据格式化为 ROLLFORWARD 工具可识别的形式,即 2007-03-15.15.15.00

  • ROLLFORWARD DATABASE testdb1 TO 2007-03-15.15.15.00 USING LOCAL TIME AND STOP

DB2 将应用指定时间戳之前的所有日志,并恢复数据库的表空间。

步骤 7. 验证已恢复的表空间和表

  • CONNECT TO testdb1
  • LIST TABLESPACES SHOW DETAIL
  • SELECT * FROM tab1

以上命令的结果允许我们确认表空间和表是否已恢复到指定的时间点。

猜你喜欢

转载自buralin.iteye.com/blog/1742936