我們可以捕獲生產環境的工作量,在測試環境上重放,從而在不影響生產環境的前提下做一些改動測試。
捕獲:需要Oracle版本為10.2.0.4或更高.
重放:需要Oracle版本為11g Release 1或更新.
本文環境:RHEL6.4 + Oracle 11.2.0.4
下面介紹一下執行Database Replay的Workflow。
1. 捕獲工作量(Workload Capture)
## 1.1 開始捕獲 ## ``` -- 創建目錄replay_dir存放捕獲信息 create or replace directory replay_dir as '/oradata/replay_dir';-- 開始捕獲工作量,10分鍾后停止
begin
dbms_workload_capture.start_capture(name => 'jydb_replay_1', dir => 'REPLAY_DIR', duration => 600);
end;
/
注:如果duration參數不指定,那么就在執行finish_capture成功后停止捕獲。
## 1.2 模擬工作量 ##
conn system/oracle@productDB
-- 數據表空間
create tablespace dbs_d_jingyu datafile size 30M autoextend off;
-- 臨時表空間
create temporary tablespace temp_jingyu tempfile size 30M autoextend off;
-- 索引表空間(可選)
create tablespace dbs_i_jingyu datafile size 30M autoextend off;
-- 假設創建用戶 jingyu 密碼 jingyu,默認臨時表空間 temp_jingyu, 默認數據表空間 dbs_d_jingyu。
CREATE USER jingyu IDENTIFIED BY jingyu
TEMPORARY TABLESPACE temp_jingyu
DEFAULT TABLESPACE dbs_d_jingyu
QUOTA UNLIMITED ON dbs_d_jingyu;
-- 賦予普通業務用戶權限
grant resource, connect to jingyu;
-- 賦予DBA用戶權限
grant dba to jingyu;
-- 業務用戶登錄
conn jingyu/jingyu@productDB
-- 刪除T1,T2兩張表
drop table t1 cascade constraints purge;
drop table t2 cascade constraints purge;
-- 創建T1,T2兩張表
create table t1( id number not null, n number, contents varchar2(4000) ) tablespace dbs_d_jingyu;
create table t2( id number not null, t1_id number not null, n number, contents varchar2(4000) ) tablespace dbs_d_jingyu;
-- 初始化向T1,T2表插入隨機測試數據
execute dbms_random.seed(0);
set timing on
insert into t1 select rownum, rownum, dbms_random.string('a',50) from dual connect by level <= 100 order by dbms_random.random;
commit;
insert into t2 select rownum, rownum, rownum, dbms_random.string('b',50) from dual connect by level <= 10000 order by dbms_random.random;
commit;
-- 查詢T1,T2表數據量
select count(1) from t1;
select count(1) from t2;
begin
for i in 1..1000
loop
execute immediate 'select t1.id from t1, t2 where t1.id = t2.t1_id and t1.n = 19';
end loop;
end;
/
-- 查詢v$sql信息
select t.EXECUTIONS, t.SQL_TEXT from v$sql t where sql_text like 'select t1.id from t1, t2 where t1.id = t2.t1_id and t1.n = 19';
## 1.3 完成捕獲 ##
-- 停止捕獲工作量
exec dbms_workload_capture.finish_capture();
<h1 id="2">2. 重放工作量(Workload Replay)</h1>
## 2.1 測試環境准備 ##
首先將目錄中生成的文件全部遷移到測試環境B目錄/u02/replay_dir中。
-- 以下步驟是在測試環境B執行
-- 創建目錄replay_dir
create or replace directory replay_dir as '/u02/replay_dir';
## 2.2 預處理工作量 ##
-- 預處理工作量
begin
dbms_workload_replay.process_capture(capture_dir => 'REPLAY_DIR');
dbms_workload_replay.initialize_replay('jydb_replay_1', 'REPLAY_DIR');
dbms_workload_replay.PREPARE_REPLAY();
end;
/
## 2.3 重放工作量 ##
-- 重放工作量 (發現有問題)
exec dbms_workload_replay.start_replay();
-- 報錯信息
*
ERROR at line 1:
ORA-20223: No replay clients have connected yet! Please issue START_REPLAY()
after one or more WRC replay clients have been started!
ORA-06512: at "SYS.DBMS_WORKLOAD_REPLAY", line 5748
ORA-06512: at line 1
--查詢
SELECT * FROM v$option WHERE parameter = 'Real Application Testing';
上述報錯因為沒有WRC重放客戶端,至少有1個WRC重放客戶端。
### 2.3.1 需要WRC模擬重演客戶端 ###
wrc mode=calibrate replaydir=/u02/replay_dir
[oracle@JY-DB01 replay_dir]$ wrc mode=calibrate replaydir=/u02/replay_dir
wrc system/oracle@testDB mode=replay replaydir=/u02/replay_dir
[oracle@JY-DB01 admin]$ wrc system/oracle@testDB mode=replay replaydir=/u02/replay_dir
### 2.3.2 開始/暫停/繼續/終止重放 ###
-- 開始重放
exec dbms_workload_replay.start_replay();
-- 暫停重放
exec dbms_workload_replay.pause_replay();
-- 繼續重放
exec dbms_workload_replay.resume_replay();
-- 終止重放
exec dbms_workload_replay.cancel_replay();
### 2.3.3 驗證重放結果 ###
-- t1表數量 應該是100
select count(1) from jingyu.t1;
-- t2表數量 應該是10000
select count(1) from jingyu.t2;
-- 查詢v$sql信息 應該是1000
select t.EXECUTIONS, t.SQL_TEXT from v$sql t where sql_text like 'select t1.id from t1, t2 where t1.id = t2.t1_id and t1.n = 19';
<h1 id="3">3. 分析和報告(Analysis and Reporting)</h1>
## 3.1 productDB部分 ##
-- 查詢捕獲信息
SELECT DBMS_WORKLOAD_CAPTURE.get_capture_info('REPLAY_DIR') FROM dual;
-- 提取報告
BEGIN
DBMS_WORKLOAD_CAPTURE.export_awr (capture_id => 18);
END;
/
-- 查詢dba_workload_captures
select id, name from dba_workload_captures;
-- 刪除捕獲信息
exec dbms_workload_capture.delete_capture_info(&i);
輸入上面查詢dba_workload_captures的id值進行刪除。
## 3.2 testDB部分 ##
-- 查詢dba_workload_replays
COLUMN name FORMAT A30
SELECT id, name FROM dba_workload_replays;
-- 收集報告
declare
capture_dir_id number;
curr_replay_id number;
replay_report clob;
begin
capture_dir_id := dbms_workload_replay.get_replay_info(dir => 'REPLAY_DIR');
select max(id) into curr_replay_id from dba_workload_replays where capture_id = capture_dir_id;
replay_report := dbms_workload_replay.report(replay_id => curr_replay_id, format => DBMS_WORKLOAD_REPLAY.TYPE_HTML);
end;
/
--刪除重放信息
exec dbms_workload_replay.delete_replay_info(&i);
輸入上面查詢dba_workload_replays的id值進行刪除。
另,在確定不需要的時候可以系統刪除重放目錄下文件。
<h1 id="4">Reference</h1>
- [Database Replay in Oracle Database 11g Release 1](https://oracle-base.com/articles/11g/database-replay-11gr1)
- OCP 認證考試指南 (1Z0-053)[M]. 清華大學出版社, 2010.