zoukankan      html  css  js  c++  java
  • oracle-snapshot too old 示例

    一、快照太老例子:
        1、创建一个很小的undo表空间,并且不自动扩展。

        create undo tablespace undo_small
        datafile '/u01/app/oracle/oradata/prod/undo_small01.dbf' size 2m
        autoextend off;

        2、让系统使用该undo表空间
        
        alter system set undo_tablespace = undo_small;
        
        3、用普通用户创建一张表,我们将建立表T 来查询和修改。注意我们在这个表中随机地对数据排序。CREATE TABLE AS
    SELECT 力图按查询获取的顺序将行放在块中。我们的目的只是把行弄乱,使它们不至于认为有某种顺序,
    从而得到随机的分布::
        
        create table t
        as
        select *
        from all_objects
        order by dbms_random.random;
        
        4、创建一个主键约束,目的是创建一个索引:
        
        alter table t add constraint t_pk primary key(object_id);
        
        5、收集表的统计信息,目的是让优化器使用索引:
        
        exec dbms_stats.gather_table_stats( user, 'T', cascade=> true );
        
        6、现在开始修改表:
        
        begin
      for x in ( select rowid rid from t )
      loop
      update t set object_name = lower(object_name) where rowid = x.rid;
      commit;
      end loop;
      end;
     
      7、在运行这个修改的同时,我们在另一个会话中运行一个查询。这个查询要读表T,并处理每个记录。
    获取下一个记录之前处理每个记录所花的时间大约为1/100 秒(使用DBMS_LOCK.SLEEP(0.01)来模拟)。在
    查询中使用了FIRST_ROWS 提示,使之使用前面创建的索引,从而通过索引(按OBJECT_ID 排序)来读出表
    中的行。由于数据是随机地插入到表中的,我们可能会相当随机地查询表中的块。这个查询只运行几秒就
    会失败:

        declare
     cursor c is
     select /*+ first_rows */ object_name
     from t
     order by object_id;

     l_object_name t.object_name%type;
     l_rowcnt number := 0;
     begin
     open c;
     loop
     fetch c into l_object_name;
     exit when c%notfound;
     dbms_lock.sleep( 0.1 );
     l_rowcnt := l_rowcnt+1;
     end loop;
     close c;
     exception
     when others then
     dbms_output.put_line( 'rows fetched = ' || l_rowcnt );
     raise;
     end;
     
     8、解决办法:
     可以看到,在遭遇ORA-01555:snapshot too old 错误而失败之前,它只处理了253 个记录。要修正
    这个错误,我们要保证做到两点:

        1、数据库中UNDO_RETENTION 要设置得足够长,以保证这个读进程完成。这样数据库就能扩大undo 表空间来保留足够的undo,使我们能够完成工作。

        2、undo 表空间可以增长,或者为之手动分配更多的磁盘空间。
        对于这个例子,我认为这个长时间运行的进程需要大约600 秒才能完成。我的UNDO_RETENTION 设置
        为900(单位是秒,所以undo 保持大约15 分钟)。我修改了undo 表空间的数据文件,使之一次扩大1MB,
        直到最大达到2GB:
        
        这里没有收到错误,我们成功地完成了工作,而且undo 扩大得足够大,可以满足我们的需要。
    在这个例子中,之所以会得到错误只是因为我们通过索引来读表T,而且在全表上执行随机读。如果不是
    这样,而是执行全表扫描,在这个特例中很可能不会遇到ORA-01555 错误。原因是SELECT 和UPDATE 都要
    对T 执行全表扫描,而SELECT 扫描很可能在UPDATE 之前进行(SELECT 只需要读,而UPDATE 不仅要读还
    有更新,因此可能更慢一些)。如果执行随机读,SELECT 就更有可能要读已修改的块(即块中的多行已经
    被UPDATE 修改而且已经提交)。这就展示了ORA-01555 的“阴险”,这个错误的出现取决于并发会话如何访
    问和管理底层表。

  • 相关阅读:
    20172315 2018-2019-1 《程序设计与数据结构》第九周学习总结
    20172315 2018-2019-1 《程序设计与数据结构》实验二报告
    20172315 2018-2019-1 《程序设计与数据结构》第八周学习总结
    20172315 2018-2019-2 《程序设计与数据结构》第七周学习总结
    20172315 2018-2019-1 《程序设计与数据结构》第六周学习总结
    20172315 2018-2019-1 《程序设计与数据结构》第五周学习总结
    20172315 2018-2019-1 《程序设计与数据结构》第四周学习总结
    20172310 2018-2019-1《程序设计与数据结构》(下)课程总结
    Do-Now—团队 冲刺博客六
    Do-Now—团队冲刺博客三
  • 原文地址:https://www.cnblogs.com/iyoume2008/p/4824267.html
Copyright © 2011-2022 走看看