当 Oracle 推出 RDBMS 12.1 版时,包含了一个有趣的新参数:“temp_undo_enabled”。默认情况下,“temp_undo_enabled”设置为 FALSE。此参数的目的是减少从 UNDO 生成的 REDO。长期的 Oracle DBA 将认识到这一点。这是其他所有人的简要说明。
当Oracle中的数据块发生变化时,会产生相应的UNDO和REDO。
UNDO(曾经称为回滚段)是用于反转更改并在其他会话中提供读取一致视图的向量。
如果更新了一行,然后发出了 ROLLBACK,则使用 UNDO 数据将块重建为原来的样子。
其他会话也使用 UNDO 来提供读取一致的视图,以便在其他会话中所做的更改不会更改您当前会话中的结果。
有关这方面的更多信息,请参阅管理撤消。
REDO 数据也是一个变化向量,但用途不同。 REDO 用于在实例或数据库恢复的情况下重建块。
当实例崩溃时,当前REDO LOGS中的REDO用于恢复到崩溃点。
该 REDO 也被写入存档日志,然后在从备份恢复数据库时用于完成恢复。
有关详细信息,请参阅管理重做日志。
在临时段上的 UNDO
想象一下,您正在应用程序中使用全局临时表(如果您尝试的话,这很容易)。
每个会话都有自己的 GTT 数据视图。创建全局临时表
许多 GTT 可用于瞬态数据的应用内转换。就其本质而言,GTT 通常不需要为实例恢复或数据库恢复而恢复。因此,不会为在 GTT 上执行的 DML 生成 REDO。
然而,GTT 上的每笔交易都默认生成 UNDO。
当 UNDO 生成时,这些 UNDO 块又受到 REDO 的保护,REDO 会填满 REDO LOGS,然后作为存档日志写出。
数据库恢复通常不需要所有这些 UNDO 和伴随的 REDO,因为它们是无法恢复的 TEMP 段。
Oracle 引入了 temp_undo_enabled 参数来帮助解决这个问题。
如果 temp_undo_enabled 设置为 TRUE,则 Oracle 不再为 GTT 的更改生成 UNDO。如果没有UNDO,则不会为UNDO 生成REDO。
这会有多大的不同?
需要进行实验。
减少返工
使用为此测试修改的 Sqlrun 版本,10 个会话同时运行 5 分钟。
在此期间,每个会话运行三个 SQL 语句。
insert into sqlrun_gtt select * from all_objects
update sqlrun_gtt set object_id = object_id + 1
merge into txcount tx
using (select sys_context('userenv','sid') sid from dual ) s
on (s.sid = tx.sid)
when matched then
update set tx.txacts = tx.txacts + 1
when not matched then
insert (sid, txacts)
values(sys_context('userenv','sid'),1)
MERGE 语句用于跟踪为每个测试执行的事务数
结果
REDO生成的差异相当大

在 temp_undo_enabled=FALSE 的情况下,生成了大约 816M 的 REDO。
在 temp_undo_enabled=TRUE 的情况下,仅生成了 2.54M 的 REDO。
如果应用程序大量使用 GTT,则只需设置这一参数即可显着减少 REDO 生成。
这种开销减少的一个副产品是,当没有生成额外的 REDO 时,能够运行另外 99 个事务。
您可能已经注意到每笔交易的 UNDO 数量增加了。 等一下,这不就是为了消除UNDO,这样就不会产生REDO了吗?
不同的是UNDO现在是Temporary UNDO,不会产生REDO。
通过加入 vundostat 和 vtempundostat 可以看到永久和临时 UNDO 使用的模式,如 allseg.sql 中所示。
SQL# @allseg
PERM TEMP
UNDO PERM TEMP UNDO
BEGIN_TIME END_TIME BLKS UNDO UNDO BLKS
------------------- ------------------- ------- ------- ------- -------
07/05/2022 12:46:20 07/05/2022 12:56:20 98309 3618
07/05/2022 12:56:20 07/05/2022 13:06:20 67406 2476
07/05/2022 13:06:20 07/05/2022 13:16:20 57562 1899
07/05/2022 13:16:20 07/05/2022 13:26:20 1459 234
07/05/2022 13:26:20 07/05/2022 13:36:20 689 266
07/05/2022 13:36:20 07/05/2022 13:46:20 45881 1570
07/05/2022 13:46:20 07/05/2022 13:56:20 59245 2029
07/05/2022 13:56:20 07/05/2022 14:06:20 7 88
07/05/2022 14:06:20 07/05/2022 14:16:20 3607 170
07/05/2022 14:16:20 07/05/2022 14:26:20 86646 3027
07/05/2022 14:26:20 07/05/2022 14:36:20 44228 1563
07/05/2022 14:36:20 07/05/2022 14:46:20 87402 3035
07/05/2022 14:46:20 07/05/2022 14:56:20 5992 580
07/05/2022 14:56:20 07/05/2022 15:06:20 64 3410 3156 109760
07/05/2022 15:06:20 07/05/2022 15:16:20 3 9 0 0
07/05/2022 15:16:20 07/05/2022 15:26:20 6 74
07/05/2022 15:26:20 07/05/2022 15:36:20 7 517 154 5360
07/05/2022 15:36:20 07/05/2022 15:46:20 0 5 0 0
07/05/2022 15:46:20 07/05/2022 15:56:20 4 118 26 905
07/05/2022 15:56:20 07/05/2022 16:06:20 102 4959 2330 80995
07/05/2022 16:06:20 07/05/2022 16:16:20 54313 4484 333 11622
07/05/2022 16:16:20 07/05/2022 16:26:20 23349 1772 0 0
07/05/2022 16:26:20 07/05/2022 16:36:20 3 104
07/05/2022 16:36:20 07/05/2022 16:46:20 0 1
24 rows selected.
这些 V$ 视图中的数据每 10 分钟更新一次,因此各种测试之间存在一些重叠。也就是说,我们可以看到在相同的 10 分钟时隙中同时使用了永久和临时 UNDO 段。
如果我能找到一种方法来为每个包含 REDO 生成,我也会将它包含在 SQL 中。在任何情况下,临时 UNDO 块都不会生成任何 REDO。
细枝末节
如果您想查看有关如何执行这些测试的详细信息,请继续阅读。
如果没有,也许您想调查一下是否有任何数据库可以从减少 GTT TEMP 段上的 REDO 中受益。
如前所述,Sqlrun 用于同时运行多个 SQL 语句。
Sqlrun 分支中的 sqlrun.pl Perl 脚本被修改为执行以下操作。
- 删除、创建和填充 stats_begin 表,用于在测试期间跟踪重做和撤消
- 删除并创建用于跟踪重做和撤消的 stats_end 表
对 sqlrun.pl 所做的更改有点杂乱无章,有相当多的硬编码。如果其中任何一个进入功能列表,它将正确完成。目前,测试是最重要的事情。
测试在 19.9 PDB 中的 UNDOTEST 帐户下运行。
SQL# @showpriv undotest
"Roles/Privileges for which user or role? - "
( Wildcards OK )
PRIV
GRANTEE TYPE PRIV NAME OWNER TABLE_NAME GRANTABLE
---------- --------------------- ---------------------- ---------- --------------------------- ---------
UNDOTEST ROLE CONNECT NO
RESOURCE NO
SYSPRIV ALTER SESSION NO
TABPRIV SELECT SYS V_$INSTANCE NO
4 rows selected.
作为 UNDOTEST 用户,最初运行 create/create.sql 脚本:
$ cat create/create.sql
drop table sqlrun_gtt purge;
create global temporary table sqlrun_gtt
on commit delete rows
as
select * from all_objects
where 1=0;
drop table txcount purge;
create table txcount ( sid number, txacts number);
文件 SQL/Oracle/sqlfile.conf 具有三个活动的 SQL 脚本:
$ grep -vE '^\s*$|^\s*#' SQL/Oracle/sqlfile.conf | grep sql
1,temp-insert.sql,
1,temp-update.sql,
1,txcount-update.sql,
这些是每个 Oracle 会话重复执行的 SQL 文件。
txcount-update.sql 脚本在测试期间更新事务数。 它实际上负责当 temp_undo_enabled = TRUE/ 时生成的相当一部分 UNDO。
运行测试
一切就绪后,运行测试就相当简单了
sqlrun.sh 的内容
./sqlrun.pl \
--exe-mode sequential \
--connect-mode flood \
--tx-behavior commit \
--max-sessions 10 \
--exe-delay 0.25 \
--db p2 \
--username undotest \
--password XXXX \
--runtime 300 \
--sqldir $(pwd)/SQL
在运行 sqlrun.sh 之前,将 job_queue_processes 参数设置为 0,以便在测试期间不会运行任何系统作业。
temp_undo_enabled 参数根据需要设置为 TRUE|FALSE,并在每个测试会话之前进行检查。
SQL# @set-temp-undo-off
System altered.
V$PARAMETER for temp_undo_enabled report for
Instance: cdb1
Date/Time: 07/05/2022 18:42:25
DEF SESS SYS
NAME INST VALUE VAL? MOD? MOD?
-------------------------------------------------- ----- -------------------------------------------------- ---- ---- ----
temp_undo_enabled 1 FALSE Y Y I
temp_undo_enabled 2 FALSE Y Y I
虽然这是一个 RAC 数据库,但所有测试都是在实例 1 上执行的。
现在运行 sqlrun.sh
$ ./sqlrun.sh
driver config file:.../sqlrun/SQL/Oracle/driver-config.json
sqlFile: /home/jkstill/oracle/dba/undo_size/temp-undo/sqlrun/SQL/Oracle/sqlfile.conf
SQL PARSER:
DEBUG: 0
sqlParmFileFQN: .../sqlrun/SQL/Oracle/sqlfile.conf
exeMode: sequential
$sqlParms: $VAR1 = {
'txcount-update.sql' => '1',
'temp-insert.sql' => '1',
'temp-update.sql' => '1'
};
Connect Mode: flood
Truncating undotest.txcount
PID: 15152
Waiting on child 15152...
PID: 0
PID: 15154
Waiting on child 15154...
PID: 0
PID: 15156
Waiting on child 15156...
PID: 0
PID: 15158
Waiting on child 15158...
PID: 0
PID: 15160
Waiting on child 15160...
PID: 0
PID: 15162
Waiting on child 15162...
PID: 0
PID: 15164
Waiting on child 15164...
PID: 0
PID: 15166
Waiting on child 15166...
PID: 0
PID: 15168
Waiting on child 15168...
Timer Check: 300
PID: 0
Timer Check: 300
Timer Check: 300
Timer Check: 300
PID: 15170
Waiting on child 15170...
PID: 0
Timer Check: 300
Timer Check: 300
Timer Check: 300
Timer Check: 300
deleting stats_begin
Timer Check: 300
Timer Check: 300
Results of dropping stats_begin: 0E0
Results of creating stats_begin: 20
~/sqlrun $
$ ps
PID TTY TIME CMD
15153 pts/4 00:00:00 perl
15155 pts/4 00:00:00 perl
15157 pts/4 00:00:00 perl
15159 pts/4 00:00:00 perl
15161 pts/4 00:00:00 perl
15163 pts/4 00:00:00 perl
15165 pts/4 00:00:00 perl
15167 pts/4 00:00:00 perl
15169 pts/4 00:00:00 perl
15171 pts/4 00:00:00 perl
15281 pts/4 00:00:00 ps
18634 pts/4 00:00:00 bash
当测试在一个 SSH 会话中运行时,另一个正忙于循环运行此监控脚本:
#!/usr/bin/env bash
USERNAME=somedba
PASSWORD=XXX
DB=p2
while :
do
sqlplus -S -L $USERNAME/$PASSWORD@$DB <<-EOF
set pause off verify off feed on term on
@@stats-end
@@stats-report
exit
EOF
sleep 5
done
此监视器允许您在测试运行时查看 UNDO 和 REDO 统计数据的变化。 它还显示了测试完成的事务数。
当事务数不再增加时,sqlrun.sh 的当前迭代已经完成。
注意:此测试不一定是文章正文中的值所基于的相同测试运行。
NAME VALUE TXCOUNT
---------------------------------------- ---------------- ----------
redo size 984,328,224 2407
undo change vector size 588,628,380 2407
2 rows selected.
20 rows updated.
Commit complete.
NAME VALUE TXCOUNT
---------------------------------------- ---------------- ----------
redo size 1,002,735,604 2452
undo change vector size 599,633,832 2452
2 rows selected.
20 rows updated.
Commit complete.
NAME VALUE TXCOUNT
---------------------------------------- ---------------- ----------
redo size 1,021,414,600 2500
undo change vector size 610,805,356 2500
2 rows selected.
2 rows updated.
Commit complete.
NAME VALUE TXCOUNT
---------------------------------------- ---------------- ----------
redo size 919,021,668 2514
undo change vector size 549,578,792 2514
2 rows selected.
2 rows updated.
Commit complete.
NAME VALUE TXCOUNT
---------------------------------------- ---------------- ----------
redo size 919,021,668 2514
undo change vector size 549,578,792 2514
投入使用
这只是启用 temp_undo_enabled 参数的好处之一,尽管它是一个引人注目的好处。
如果您正在寻找减少 Oracle 12c+ 数据库中 REDO 生成的机会,请务必测试此参数的使用。
我希望你觉得这篇文章有帮助。 随意提出任何问题或在评论中分享您的想法,并确保注册以获取更新。
原文标题:Big Savings on Oracle REDO Via Temp UNDO
原文作者:Jared Still
原文地址:https://blog.pythian.com/big-savings-on-oracle-redo-via-temp-undo/




