Chinaunix首页 | 论坛 | 博客
  • 博客访问: 838195
  • 博文数量: 199
  • 博客积分: 6363
  • 博客等级: 准将
  • 技术积分: 2225
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-28 10:01
个人简介

来自农村的老实娃

文章分类

全部博文(199)

文章存档

2017年(1)

2014年(2)

2013年(3)

2012年(6)

2011年(26)

2010年(34)

2009年(50)

2008年(44)

2007年(33)

我的朋友

分类: Oracle

2007-11-27 10:08:44

需要在数据库中进行更改时 — 无论是进行微小的改动(如变更初始化参数和数据库属性)还是进行不可避免的较大改动(如应用补丁集),您最关心什么?对于您的到 Oracle 数据库 11g 的升级,您最关心的是什么?

对我而言,我最关心的是更改是否会带来“破坏性”风险。即使微小的改动也有可能引发多米诺骨牌效应,最终导致严重后果。

为了将这种风险降至最低,许多厂商在类似于生产环境的控制环境中进行更改,应用类似于生产系统的负载并观察随之产生的影响。复制生产系统非常简单(至少从技术层面上讲),但再现负载却是另一回事。说起来容易做起来难。

多数机构会采用一些可自动运行以模拟真实用户活动的第三方负载生成工具进行尝试。在大多数情况下,这种方法是可以的,但其始终无法真正忠实地再现生产数据库负载。这些第三方工具只是通过不同参数执行预编写的查询若干次;您必须向这些工具提供查询并给定其可以随机使用的参数范围。这并不能代表您的生产系统负载,而仅仅是运行了一小部分执行了若干次的生产负载,因此,这只是对 1% 的应用程序代码进行了测试。最糟糕的是,这些工具要求您自己提供所有来自生产负载的查询,对于小型应用程序而言,这可能需要数周或数月,对于复杂些的而言,则可能需要多达一年的时间。

如果可以,在数据库本身内记录所有数据库操作(与 DML 相关的操作及其它),而后按这些操作出现的真实顺序进行重放,难道不是一种更好的方法吗?

数据库重放概述

Oracle 数据库 11g 将为您带来诸多好处。新的数据库重放工具好似数据库内的 DVR。使用该独特的方法,可如实地以二进制文件格式捕获 SQL 级别以下的所有数据库活动,然后在同一数据库或不同数据库内进行重放(这正是在进行数据库更改之前您希望做的)。您还可以自定义捕获流程,以包括或排除某些特定类型的活动。

数据库重放与另一个工具 SQL 性能分析器共同构成了 Oracle 数据库 11g 的“真正应用测试”选件。这两个工具之间的主要不同在于涉及的范围:数据库重放适用于捕获和重放数据库内的所有(符合某些筛选条件)活动,而 SQL 性能分析器可用于捕获特定的 SQL 语句并对其进行重放。(在数据库重放中,您无法查看或访问捕获到的特定 SQL,而在 SQL 性能分析器中则可以)。后者的一个显著优势是 SQL 调整,因为您可以调整由应用程序执行的 SQL 语句并评估其影响。(本系列即将推出有关 SQL 性能分析器介绍的文章。)

理论上,数据库重放的工作顺序如下图所示。

图 1
  1. 启动一个记录数据库活动的捕获流程。
  2. 该流程将活动写入名为“capture files”的特殊文件,该文件位于 /capture directory/ 目录中。
  3. 稍后,停止捕获流程,将这些捕获文件移至位于 /replay directory/ 目录中的测试系统。
  4. 启动一个重放流程和若干重放客户端,以重放这些捕获文件。
  5. 这些捕获文件将在测试数据库上应用。
因此,数据库重放可以提供哪些第三方工具不能提供的优势?一些工具仅仅重放若干您提供的复合语句。而数据库重放不需要您提供 SQL 语句。由于它将捕获 SQL 之下的所有活动,因此您不会遗漏任何可能导致性能问题的关键操作。此外,您可以有选择地(针对特定用户、程序等)进行捕获,还可在捕获负载时指定时间期限,可以重放导致问题的特定负载,而不是整个数据库。

例如,您注意到月末利息计算程序导致问题出现,并猜想更改参数将简化流程。您必须做的是捕获月末程序运行期间内的负载,在测试系统上对参数进行更改,然后在该测试系统上重放捕获文件。如果性能有所提升,则表明此解决方案可行。如果性能没有提升,这也仅仅是个测试系统而已。您不会妨碍到生产数据库的运行。

在我看来,单为了使用该工具,也值得升级到 Oracle 数据库 11g。下面将介绍该工具的工作原理。

捕获

第一个任务是捕获数据库中的负载。所有任务都可通过命令行或 Oracle 企业管理器数据库控制完成,但此处将使用后者。
  1. 捕获到的负载存储在系统中的文件上,这些文件是名副其实的“摄像机”内的“磁带”。该目录应当为空。因此,第一个任务是创建目录(如果还没有此目录)。对于本例,创建的目录名为 /home/oracle/dbcapture。
      $ cd /home/oracle
      $ mkdir dbcapture
    
  2. 在数据库中为该目录创建一个目录对象:
    SQL> create directory dbcapture as '/home/oracle/dbcapture';
    
    
    目录创建完成。
  3. 现在,可以开始捕获了。为了演示真实场景,将创建一个简单的测试工具,该工具将生成许多 INSERT 语句并插入到一个名为 TRANS 的表中。

    下面是一个可完成此任务的小的 PL/SQL 代码片断。该代码片断将生成 1,000 个插入语句并进行执行。(注意,此代码片段将生成 1,000 个不同的插入语句,而不是在同样的语句或程序中执行 1,000 次插入操作。)

    declare
      l_stmt varchar2(2000);
    begin
      for ctr in 1..1000 loop
         l_stmt := 'insert into trans values ('||
            trans_id_seq.nextval||','||
            ''''||dbms_random.string('U',20)||''','||
            'sysdate - '||
            round(dbms_random.value(1,365))||','||
            round(dbms_random.value(1,99999999),2)||','||
            round(dbms_random.value(1,99))||')';
         dbms_output.put_line(l_stmt);
         execute immediate l_stmt;
         commit;
      end loop;
    end;
    
    只创建包含以上内容的文件;不要运行。将该文件命名为 add_trans.sql。

  4. 在现实情况中,您可能会在不同的数据库上运行重放。但是,在此处,针对我们的目的,您将只是闪回同一数据库并重放那里的活动。您可以通过创建名为 GOLD 的恢复点来标记该场所。
    SQL> create restore point gold;
    
    (第 1 步到第 4 步仅对本课而言必不可少。如果没有目录对象,则在生产环境中执行操作时无需这些步骤。)

    现在,准备开始捕获。导航到 Oracle Enterprise Manager Database Control 中的 Database Replay 主页面。在该主页中,选择 Software and Support(如下图所示,标记为“1”)

  5. 图 2

  6. 单击 Database Replay(标记为“2”)启动 Database Replay 页面(如下所示)。

    图 3

  7. 在左侧窗格中,您将看到一系列活动。选择第一个活动 (Step 1:Capture Workload),方式是单击它旁边的 Go to Task 图标。

  8. 下一个屏幕将显示三个您应在启动捕获流程之前仔细检查并确认的假设:

    • 当前数据库可以在重放系统上恢复到负载捕获开始时的 SCN
    • 有足够的磁盘空间来保存捕获的负载
    • 在负载捕获开始之前已准备好重启数据库(如果您选择这样做)

  9. 选中所有复选框进行确认。

  10. 单击 Next

  11. 下一个屏幕有两个不同的操作项。在屏幕的上半部分,您将看到两个单选按钮,您可通过这两个按钮来选择是否希望在捕获流程前重启数据库。

    启动捕获流程后,可能会有一些正处于运行中的事务,其中并非所有都可进行捕获。重启数据库将使这些正处于运行中的事务无效。此外,共享池可能具有数个 SQL 语句,其中一些可缓存和固定。这可能会与捕获的负载相冲突。重启数据库可清除这些“干扰”。而且,重启数据库可以为您提供一个干净备份在测试系统上进行恢复,从而确保您在与生产系统的 SCN 号相同的系统上重放活动。

    出于以上这些原因,特别是第一个,Oracle 建议在捕获之前重启数据库(该选项为默认设置)。但这不是必须的。如果不希望重启,请选择另一个单选按钮。

  12. 屏幕底部显示的内容如下所示。

    图 4


    现在,您将记录捕获流程在捕获活动时将考虑的过滤器。默认有两个过滤器:排除所有来自 Oracle Management Server 的活动和来自 Oracle Management Agent 的活动。

    您也可以添加其它过滤器。例如,要添加排除所有 Perl 程序的过滤器,可单击 Add Another Row 并在域“Filter Name”和“Value”中分别输入“perl”和“%perl%”。同样,纠正默认参数中的小错误 — Oracle Management Agent 过滤器的值应是“%emagent%”,而不是“emagent%”。

    或者,假设您希望排除所有 SYS 用户操作。那么,您需要从 Session Attribute 下拉框中选择 USER,并在“Value”列中输入 SYS。

  13. 单击 Next。这将显示一个类似如下所示的屏幕:

    图 5

  14. 在该屏幕中,从下拉框中选择将在其中存储捕获文件的目录名。本例中已使用了目录 DBCAPTURE。如果您没有在以上步骤中创建该目录,还可通过单击 Create Directory Object 进行创建。然后单击 Next
  15. 在下一个屏幕中,您将看到 Job Details(作业细节),如作业执行时间等。选择单选按钮 Immediate 立即执行作业。

  16. 在该页面上填写其它细节,如 OS 用户名、SYS 口令等,并单击 Next

  17. 下一个屏幕标为“Step 5 of 5”,其中将显示您输入的所有信息,如作业名和排除过滤器。如果所有内容都符合您的要求,则单击 Submit。否则,可返回以进行修改。

  18. 一旦单击了 Submit,负载捕获就将开始。您将看到一个确认屏幕,如下所示。

    图 6


    注意 Status,其显示为“In Progress”。
  19. 现在,该工具正在捕获负载,从 SQL*Plus 提示符运行您的模拟负载。当然,在实际的系统中,无需运行任何模拟;只需让捕获流程运行一段时间以捕获所有负载。
    SQL> connect scott/tiger
    SQL> @add_trans
    
    这将在表 TRANS 中执行 1,000 个插入语句。

  20. 负载完成后,单击 Stop Capture

  21. 您已经将捕获的负载成功地存储到 /home/oracle/dbcapture 目录中的文件里。

预处理

现在,负载已捕获,可进行重放了。通常,您希望在单独的测试系统中进行重放,因此需要将目录 /home/oracle/dbcapture 中的文件复制到一个新的主机。请确保在将文件复制到该目录时,该目录为空。出于教学目的,您将使用同一个数据库进行重放。

在同一数据库中进行重放并不常见,但有可能出现。例如,您可能希望在主系统中重放事务,测试完成后闪回至起始点。您可能会中断一个时段,以在期间测试参数更改(您将在同一数据库中进行此更改)的效果。

您需要在播放捕获的负载之前对其进行预处理。预处理可使这些捕获的文件为重放做好准备。

  1. 转至 Database Replay 主页面。
  2. 选择 Step 2:Preprocess Workload
  3. 从下拉列表框中选择目录对象。这将显示捕获的负载。在本例中,该目录对象是 DBCAPTURE。如果您还没有创建目录对象,单击相应的按钮即可轻松创建目录。
  4. 单击 Preprocess Workload
  5. 在下一个页面中,将要求您提供作业名和相关细节,如主机用户名和口令。如果不想指定作业名,接受默认值。选择立即运行该作业。主机用户 ID 和口令应已填充。如果还没有,输入相应的值,单击 Submit
  6. 在下一个页面中,您将看到确认信息和一个可用于查看作业状态的链接。单击该链接。
  7. 刷新该屏幕,直至您看到状态为“Succeeded”。
现在,负载已经过预处理,可用于重放了。

重放

捕获负载并进行预处理后,您就可在测试数据库中进行重放了。出于教学目的,您在同一数据库中预处理了负载,并将使用同一数据库重放这些活动。为此,您必须将数据库重置回起始点。您可以通过将其闪回到在捕获流程期间创建的恢复点 GOLD 来轻松实现此目的。

SQL> shutdown immediate;
... database shuts down ...
SQL> startup mount
... instance starts and mounts the database ...
SQL> flashback database to restore point gold;
... database will be flashed back ...
SQL> alter database open resetlogs;
... database is opened ...
现在,您处于负载启动之前的一个点,可以重放之前捕获的负载了。按照以下步骤对其进行重放。
  1. 从 Database 主页转至 Database Replay 主屏幕,如“Capturing”部分中所示。

  2. 从菜单中选择 Step 3:Replay Workload。这将带您进入 Replay 主屏幕。

  3. 您将看到一个用于选择目录的下拉框。选择重放文件所在的目录。这是目录对象;不是实际的 UNIX 目录。在之前的示例中,您使用了目录对象 DBCAPTURE,因此将其选中。如果您还没有创建目录,可单击 Create Directory 创建一个目录对象。

  4. 单击右上角的 Setup Replay

  5. 下一个屏幕将显示即将发生的事情的信息列表。以下为每条信息项的相关说明。

    • Restore Database(恢复数据库)— 重放之前捕获的负载时,可能需要在测试系统上执行此操作。您如何构建测试系统?您可能将生产数据库恢复到测试系统并对其进行恢复。最大的可能是,在此活动中,生产数据库没有关闭,因此您的恢复可能并不完全。在这种情况下,确认恢复操作已执行至捕获和预处理阶段指定的 SCN 号。

      本例中,您将数据库闪回至该 SCN 号。因此,您遵循了规定。

    • Perform System Changes(执行系统更改)— 这是为什么要首先执行重放的原因:测试系统更改,如参数更改或设置更改。当然,您需要在重放之前进行更改。

    • Resolve References to External Systems(解决对外部系统的引用)— 假设您已经在生产数据库中具有了一个指向 /home/appman/myfiles 的目录对象,而测试系统上不存在该目录。在重放时,对该目录的引用将失败。同样,源系统中的所有数据库链接也将在测试系统中失败(如果它们不存在)。因此,您需要通过创建或更改目录来解决这些问题。您可以利用下一个屏幕对其进行更改。

    • Set Up Replay Clients(设置重放客户端)— 了解如何在后续步骤中执行该操作。

  6. 单击 Continue,这将显示如下所示的屏幕:


    图 7


    您可以通过单击页面上显示的链接更改所有非引用参数。请注意,单击任何一个链接都将会离开 Database Replay 页面。因此,最好在 SQL*Plus 中对这些链接进行单独更改。单击 Continue

  7. 输入 Replay Name 或接受默认值。

  8. 下一个屏幕将显示一些由于未解决的对数据库链接、目录等的引用而可能导致的问题。


    图 8


    如果愿意,可以在屏幕右侧更改重放系统。在本例中,由于在同一数据库上运行,因此本步骤并非必须。

  9. 单击 Next。这将显示如下所示的屏幕:

    图 9


    该屏幕将显示重放流程正在等待重放客户端。重放客户端的执行并不在 Database Control 屏幕内进行。这些客户端程序读取捕获的负载并对其进行重放。程序名为 wrc(在 UNIX 和 Windows 系统上均是该名称)。要启动重放客户端,您需要转至 UNIX 提示符并执行以下命令行:
    $ wrc userid=system password=* replaydir=/home/oracle/dbcapture
    
    当然,您需要提供正确的 SYSTEM 口令。如果捕获文件存储在另一个地方,则需更改目录名。应返回以下消息:
    Workload Replay Client: Release 11.1.0.4.0 - Beta on Wed Jun 6 01:47:53 2007
     
    Copyright (c) 1982, 2006, Oracle.  All rights reserved.
     
    Wait for the replay to start (01:47:53)
    
    此时,重放客户端仅仅是等待重放管理程序(数据库控制)告知其启动。您可以决定是否启动多个客户端来并行处理负载。

  10. 立即转至 Database Control 屏幕。您应当看到该屏幕已更改,其中显示已连接重放客户端。该屏幕将显示客户端连接的主机名、操作系统进程 ID 等。

    图 10

  11. 单击 Next,然后单击 Submit 启动重放流程。如果现在转至 UNIX 会话,您会看到另一条消息:“Replay started (01:49:56)”。该屏幕将通过进度条来显示目前已处理的数据量。

  12. After some time the UNIX session will show "Replay finished (01:50:35)".此时,如果查看 Database Control 屏幕,您将看到该屏幕类似如下所示:

    图 11

  13. 其中显示了重放作业的详细状态。左上角的关键域“Status”显示为“Completed”,指示作业已完成。
  14. 现在可以进行运行分析了。该屏幕在下半部分(标题“Comparison”下)显示了一些量度。在本例中,重放在 41 秒内完成,是捕获流程所花时间2 分 14 秒的 30.6%。这是个好消息吗?您实施的更改有效吗?

    不一定。看看下一个量度:Database Time(数据库时间)。该值没有变化 — 大约 2 秒钟。因此,您实施的这些更改没有带来任何明显的改善。

  15. 但请勿就此停下。要进行更为综合的分析,可比较捕获期间一段时期的自动负载信息库 (AWR) 快照和重放,看看众多其它度量(如栓锁争用、锁定、重做产生、一致获取等)之间的差异,以使您更好、更清晰地了解更改所带来的影响。

用例

数据库参数更改 — 假如,您要更改参数 db_file_multiblock_read_count 的默认值,那么是从 16 改为 256 还是 128?亦或是将其设为 64 或 32?选择有限,但影响可能无限;更改此值会对优化程序带来极大影响,对某个查询有益的更改可能会破坏另外 100 个查询。如何确定该参数的最佳值?

数据库重放可轻松应对这种情况。您可以从生产系统捕获负载,而后将捕获的负载移至不同的测试系统中,并将 db_file_multiblock_read_count 设为 32,然后重放负载。之后,您可以将数据库闪回至初始状态,将该值设为 64,并重放相同的负载。您可以针对该参数所有可能的值重复执行这一过程:闪回、设置值、重放捕获的负载。每次重放时,您可捕获重放前后的 AWR 快照并进行比较。然后选择可带来最佳整体结果的参数值。如果没有数据库重放,则根本不可能确定出最佳值。

操作系统升级 — 您计划升级操作系统或只是应用一个小补丁来修复 I/O 问题,但您如何能确保它不会带来任何破坏或带来一些其它问题?很简单:只要捕获负载并在应用补丁的测试系统中对其进行重放。该方法同样也适用于内核参数更改。

应用补丁 — 假设您发现一个错误,并且有相应的补丁可用。但您无法确保其会对现有操作产生何种影响,当然,您也可以和企业中 1000 位其他用户共同找出答案。数据库重放将为您解决这一难题。

调试 — 总是会有一些会带来意外结果的令人讨厌的程序。幸运的是,有了数据库重放,调试变得前所未有的轻松。只需在程序运行期间捕获负载,并移至一个新系统,更改程序逻辑以加入一些调试信息,而后重放负载、分析输出并解决问题。如果第一次并未凑效,不要失去信心。重复该过程(从重放开始;无需再次捕获)直至找到解决方案。

对象更改 — 您希望添加索引或将索引从 b 树转换为位图。这会对 INSERT 语句产生何种影响?会在何处产生影响?不要猜测;只需捕获负载并在测试系统中进行重放即可。

数据库升级 — 这是梦寐以求的更改确保。升级至 Oracle 数据库 11g 的时代已经到来。最大的问题是:您所有的应用程序都会正常运行甚至是表现更好吗?无需多虑,只要从 Oracle 数据库 10g 捕获负载并在 Oracle 数据库 11g 中进行重放即可。您不是在新版本上测试一些复合事务,而是在测试应用程序每天都在使用的 SQL。如果有些事情并未按计划进行,则在新系统中对其进行调整,直至您获得完全满意的结果。

(注:截至本文撰写之日,Oracle 数据库 11g 还只有测试版,尚不支持来自 Oracle 数据库 10g 的捕获。但是,该功能将在 Oracle 数据库 11g 的生产版中提供。)

平台更改 — 假设您希望将数据库平台从 Solaris 移植到 HP-UX(其中没有提供适用于文件系统的异步 I/O)。性能是否还会一样?为什么要猜测?只要捕获 Solaris 中的负载并在 HP-UX 中进行重放即可。

转换到 Oracle 真正应用集群 (RAC) — 这是一个普遍问题:您计划将数据库从单一实例转换为 RAC 实例。应用程序表现是否如初?获取答案的唯一方法是运行实际的负载,对其进行捕获,而后在 RAC 数据库中进行重放。

结论

更改从来都是困难重重,但也不再是无法忍受。您可以通过使用新的数据库重放工具捕获最终用户放入系统中的确切活动,而后在测试系统上进行重放,以精确地衡量更改影响来降低多数风险,而这些都只需几下鼠标点击和键盘敲击即可实现。请记住,您还可以测试应用程序的功能,并不仅仅限于性能

阅读(3980) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~