是否该清除in_memory_undo?
_in_memory_undo=false
正如前面已经谈到的,默认情况下_in_memory_undo的值被设置为true,下面的测试和前面的一样,除了将_in_memory_undo设置为false外,我们一起来看看会发生什么,首先使用ARCHIVE LOG LIST命令验证实例仍然处于非归档日志模式下,使用SHOW PARAMETER UNDO命令验证_in_memory_undo参数被设置为false。
_in_memory_undo=false
=================================================
SQL> archive log list
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination /opt/app/oracle/product/11.1.0/db_1/dbs/arch
Oldest online log sequence 330
Current log sequence 339
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_in_memory_undo boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
=================================================
Test : Normal processing
: _in_memory_undo=false
=================================================
我们再次创建一下用于测试的表FLASH_TEST,仍然只包括一列,最初的数据行只有5行,创建表,插入数据,查询最初数据项的语句请参考前面,这里就不啰嗦了。
现在要做的验证是看闪回查询是否仍然有效,以及清除共享池和缓冲区后是否仍然有效:
COL1
----------
1
2
3
4
5
alter system flush shared_pool;
SQL> SELECT * FROM flash_test AS OF TIMESTAMP TO_TIMESTAMP ('05272009:10:07:04','MMDDYYYY:HH24:MI:SS');
COL1
----------
1
2
3
4
5
alter system flush buffer_cache;
SQL> SELECT * FROM flash_test AS OF TIMESTAMP TO_TIMESTAMP ('05272009:10:07:04','MMDDYYYY:HH24:MI:SS');
COL1
----------
1
2
3
4
5
至此,完全说明闪回查询与归档日志模式无关,而是使用了物理结构如undo和重做日志。
=================================================
Test : Normal processing
: Bounce the database
: _in_memory_undo=false
=================================================
这样就看出一个很有趣的现象了,当把 _in_memory_undo设为true时,在经历数据库关闭再打开后,闪回查询就无效了,而将 _in_memory_undo=true设为flase后,将数据库关闭再打开,闪回查询却仍然有效,这和Oracle的文档说明截然相反,现在我们只需要验证数据库启动时没有载入什么东西到内存中就可以证明闪回查询与清除共享池没有关系,进一步说明是通过物理结构(undo/redo)重构查询结果的。
ORACLE_HOME_LISTNER is not SET, unable to auto-stop Oracle Net Listener
Usage: /opt/app/oracle/product/11.1.0/db_1/bin/dbshut ORACLE_HOME
Processing Database instance "db11FS": log file /opt/app/oracle/product/11.1.0/db_1/shutdown.log
[oracle@ludwig ~]$ dbstart
ORACLE_HOME_LISTNER is not SET, unable to auto-start Oracle Net Listener
Usage: /opt/app/oracle/product/11.1.0/db_1/bin/dbstart ORACLE_HOME
Processing Database instance "db11FS": log file /opt/app/oracle/product/11.1.0/db_1/startup.log
alter system flush shared_pool;
alter system flush buffer_cache;
SQL> select * from flash_test;
COL1
----------
1
2
3
4
5
6
7
8
9
10
10 rows selected.
SQL> SELECT * FROM flash_test AS OF TIMESTAMP TO_TIMESTAMP ('05272009:10:07:04','MMDDYYYY:HH24:MI:SS');
COL1
----------
1
2
3
4
5
=================================================
Test : Normal processing
: Switching through archive logs
: _in_memory_undo=false
=================================================
现在需要我们做的是做什么让闪回查询失效,尽管不是一个详细的说明,但展示了Oracle内部是如何工作的,这很有趣!现在我们把数据库切换到归档日志模式,然后重新清除一遍共享池和缓冲区,有趣的是,闪回查询仍然有效。
alter system flush shared_pool;
alter system switch logfile; (performed enough times to cycle through redo logs)
alter system flush buffer_cache;
alter system flush shared_pool;
SQL> SELECT * FROM flash_test AS OF TIMESTAMP TO_TIMESTAMP ('05272009:10:07:04','MMDDYYYY:HH24:MI:SS');
COL1
----------
1
2
3
4
5
=================================================
Test : Normal processing
: Switching UNDO tablespaces
: _in_memory_undo=false
=================================================
于是推断出闪回查询的结果应该来自undo日志,于是我们再次清除共享池和缓冲区的数据,并切换到新的undo表空间,令人惊奇的是闪回查询仍然有效,我不知道你怎么样,我是感觉很困惑了。
但如果将undo表空间删掉的话,就会出错了:
alter system flush buffer_cache;
alter system flush shared_pool;
SQL> SELECT * FROM flash_test AS OF TIMESTAMP TO_TIMESTAMP ('05272009:10:07:04','MMDDYYYY:HH24:MI:SS');
SELECT * FROM flash_test AS OF TIMESTAMP TO_TIMESTAMP ('05272009:10:07:04','MMDDYYYY:HH24:MI:SS')
*
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number with name "" too small
虽然本文没有找出Oracle究竟都在那些地方隐藏了undo数据,但提供了_in_memory_undo参数设置对比,由于这个参数被设计用于提高在内存中查询避免直接访问磁盘的性能,同时也提出了一个有趣的问题“是否有需要设置_in_memory_undo参数?”,很明显,将这个参数设为false有一定的好处,但我要申明一点的是要注意你的Oracle版本是否和我的一致,否则有可能你看到的和我看到可能不一样!