技术开发 频道

log buffer及日志管理深入分析及性能调整(三)


3.4 减少生成的重做记录的方法
    要优化日志缓冲区的使用,最直接、最容易看到效果的方法当然就是阻止重做记录的产生了。也就是说对DML语句不记录数据块的改变过程,从而减少对日志缓冲区的使用。但是,毫无疑问,这完全违背了oracle设立日志缓冲区以及联机日志文件的目的。由于没有产生对数据块变化的记录,那么如果数据库发生崩溃,将导致无法恢复到数据库崩溃前一秒的状态,也就必然发生数据丢失。

    通过使用NOLOGGING短语或者append提示来阻止重做记录的产生。该短语可以用在表空间上,表示该表空间里的对象缺省都不产生日志。也可以将表或者索引定义为NOLOGGING,这样该表上的DML操作都不生成重做记录,而对索引的重建也不生成重做记录。还可以直接用在以下的SQL语句中:
1) 直接路径装载(Direct Loader)以及直接路径插入(对insert使用append提示:insert /*+ append*/)。
2) create table table-name NOLOGGING as select …(CTAS)
3) alter table table-name NOLOGGING move tablespace tablespace-name
4) create index index-name NOLOGGING …
5) alter index index-name NOLOGGING rebuild…
6) 分区操作中,可以添加NOLOGGING短语。
7) truncate命令总是以NOLOGGING方式执行。

比如,我们来看一个在SQL语句中添加NOLOGGING选项的例子,数据库运行在归档模式下。 
SQL> select value from v$mystat a,v$statname b 2 where a.statistic#=b.statistic# and b.name='redo size'; VALUE ---------- 10592 SQL> create table t1 as select * from dba_objects; SQL> select value from v$mystat a,v$statname b 2 where a.statistic#=b.statistic# and b.name='redo size'; VALUE ---------- 5796480
很明显的,正常情况下创建表时生成了5785888(5796480-10592)字节,也就是约5.5M的重做记录。
SQL> drop table t1; SQL> select value from v$mystat a,v$statname b 2 where a.statistic#=b.statistic# and b.name='redo size'; VALUE ---------- 5801424 SQL> create table t1 NOLOGGING as select * from dba_objects; SQL> select value from v$mystat a,v$statname b 2 where a.statistic#=b.statistic# and b.name='redo size'; VALUE ---------- 5909952
    可以看到,当使用NOLOGGING选项创建表时,只生成了108528(5909952-5801424)字节,也就是约106K的重做记录。原来生成的大约5.5M日志就是表t1本身的容量,而使用NOLOGGING以后,直接写入磁盘,没有对表t1自身的数据记录日志,所生成的106K的重做记录只是在创建表时,对所修改的数据字典的保护。不过这里要注意一个问题,就是我们的测试环境是归档模式,如果在非归档模式下,则对CTAS命令使用NOLOGGING选项所产生的日志与不使用NOLOGGING选项所产生的日志几乎没有差别。这是因为非归档模式下的CTAS命令本身就不会对所创建的表的数据记录日志。
现在我们来测试一下在非归档模式下,使用NOLOGGING选项来定义索引时的情况。
SQL> select index_name,logging from user_indexes where table_name='T1'; INDEX_NAME LOG ------------------------------ --- IDX_T1_OBJECTNAME YES SQL> select value from v$mystat a,v$statname b 2 where a.statistic#=b.statistic# and b.name='redo size'; VALUE ---------- 4170024 SQL> alter index idx_t1_objectname rebuild; SQL> select value from v$mystat a,v$statname b 2 where a.statistic#=b.statistic# and b.name='redo size'; VALUE ---------- 6257600 可以看到,正常重建索引时生成了2087576(6257600-4170024)字节,也就是大约2M的重做记录。 SQL> alter index idx_t1_objectname nologging; SQL> select value from v$mystat a,v$statname b 2 where a.statistic#=b.statistic# and b.name='redo size'; VALUE ---------- 6259968 SQL> alter index idx_t1_objectname rebuild; SQL> select value from v$mystat a,v$statname b 2 where a.statistic#=b.statistic# and b.name='redo size'; VALUE ---------- 6325568
将索引定义为NOLOGGING以后,再次rebuild只生成了65600(6325568-6259968)字节,也就是64K的重做记录。注意,这是在非归档模式下的测试结果。可以看到这与CTAS创建表有所不同,CTAS在非归档模式下不会记录数据的变化,只会记录数据字典的变化。而在非归档模式下创建索引时,如果不使用NOLOGGING选项,则既会记录数据字典的变化,也会记录索引数据块的变化。
  现在,我们将前面那个CTAS例子中(归档模式下)的当前的联机日志文件(含有用NOLOGGING选项创建表t1的重做记录)转储出来看看这时的重做记录是怎样的。我们找到表t1对应的object id为51535,然后对转储出来的日志文件进行搜索,可以发现很多类似下图五这样的内容,这部分内容表示对数据字典的修改所生成的重做记录。

图五
  我们同时还会发现很多类似下图六的内容,这部分内容就说明为何使用了append以后,并没有修改数据字典,为何还是产生了大约106K的重做记录的原因。不管使用NOLOGGING还是append,都会对所修改

图六
  的数据块进行标记,标记这些数据块已经出现软损坏(soft-corrupt)了,在恢复是不能使用。这时改动向量的类型是INVLD。同时会记录起始数据块的地址(下图的DBA:0X1000114),以及后面有多少个数据块(下图的BLKS:0x0005)被标记为损坏。当使用这样的重做记录进行恢复时,系统会报ORA-273错误。
0
相关文章