专门做反季的网站,建个平台需要多少资金,吉林省建设厅官网查询,上海十大室内设计公司排名现象#xff1a; 应用的夜维从夜里00:00开始执行#xff0c;但因为hang的原因(暂时猜测为夜维处理的某条数据和当前应用正常处理的某条数据相同#xff0c;出现前后等待同一资源锁的现象)#xff0c;直到第二天白天09:25左右才继续执行#xff0c;但此时应用日志记录… 现象 应用的夜维从夜里00:00开始执行但因为hang的原因(暂时猜测为夜维处理的某条数据和当前应用正常处理的某条数据相同出现前后等待同一资源锁的现象)直到第二天白天09:25左右才继续执行但此时应用日志记录 snapshot too old: rollback segment number 29 with name _SYSSMU29$ too small 原因分析 因hang导致夜维的DELETE语句一直处于等待状态(超过一天)直到资源锁释放但此时由于开始存放于UNDO中的前镜像超过UNDO_RETENTION参数设置的时间且这是高并发的一个系统很快可能就会被应用session覆盖UNDO中的记录导致无法找到UNDO中的记录产生一致性读因此报错ORA-1555此次执行失败。 虽然分析可能是这个原因但是是什么语句让这个系统的夜维语句hang还没有找到有待进一步分析。。。 引申 不过从这个报错现象可以接触到ORA-1555这个经典的错误号尤其是在生产中也是一种不多见的情况尤其在现在UNDO基本都是用Oracle自动管理方式且磁盘空间分配都比较大的情况下。 这个ORA-1555的错误是Oracle回滚段错误中的一种经典。UNDO用于记录DML操作数据的前镜像ORA-1555的错误简单用一句话总结我觉得就是当DML语句需要用UNDO记录的数据找到前镜像时该记录已经被覆盖导致无法利用UNDO中的记录完成一致性读。当然Oracle也有UNDO_RETENTION等参数避免这种情况的产生但仍旧可能发生原因有多种解决方法也有多种下面就简单说明介绍下。 首先Tom、hellodba等高人也对ORA-1555有过经典的介绍。从原因来讲ORA-1555的错误原因归为两种一是一致性读一个是延迟块(锁)清除。 和ORA-1555相关的参数 1、UNDO_RETENTION。 UNDO_RETENTION参数设置了回滚段中被提交或回滚的数据强制保留时间但并不是说超过这个时间回滚段中的数据就会被清除而是等待后面的事务产生的回滚数据覆盖之前的。 2、对于Oracle 9i及以上版本有两种管理UNDO的方法由UNDO_MANAGEMENT参数指定手动管理UNDO和自动管理UNDO的区别手动管理是会回绕的会尽可能地重用UNDO空间Oracle会扩展UNDO段而不是回绕从而保证UNDO_RETENTION的时间要求。因此从这可以看出为了避免ORA-1555使用自动管理UNDO的方法也许可以一定程度上降低概率。 概念介绍 1、一致性读(摘自hellodba的blog“http://www.hellodba.com/reader.php?ID170langCN”) Oracle通过回滚段进行一致性读即避免了脏读又大大减少了系统的阻塞、死锁问题。Oracle更新数据块(Data Block Oracle中最小的存储单位)时会在两个地方记录下这一更新动作。一个是重做段(Redo Segment)是用于数据库恢复(Recover)用的。一个是回滚段(UNDO Segment)而回滚段是用于事务回滚(Rollback)的(我们只关心回滚段了)。并在数据块头部标示出来是否有修改数据。一个语句在读取数据快时如果发现这个数据块是在它读取的过程中被修改的(即开始执行读操作时并没有被修改)就不直接从数据块上读取数据而是从相应的回滚段条目中读取数据。这就保证了最终结果应该是读操作开始时的那一时刻的快照(snapshot)而不会受到读期间其他事务的影响。这就是Oracle的一致性读也可以叫做多版本(Multi-Versioning)。 2、延迟块清除(摘自hellodba的blog“http://www.hellodba.com/reader.php?ID170langCN”) 当Oracle更新数据块时会在回滚段(UNDO Segment)记录下这一更新动作。并且产生一个Cleanout SCN在回滚段中会产生对应的Transaction ID以及相应的数据记录镜像。并在对应的数据记录上产生锁标志。在事务提交(commit)前会在数据块的头部记录下这个Cleanout SCN(Csc)号、Undo Block Address(Uba)和Transaction ID(Xid)并且在在对应Interested Transaction List(Itl)中设置锁标志记录这个事务在这数据块中产生的锁的数目同时在对应修改的数据记录上打上行级锁标志并映射到对应的Itl去。当提交时并不会一一清除掉所有锁标志而是给对应的Itl打上相应标志告诉后面访问该数据块的事务相应的事务已经提交。这就叫做快速提交(Fast Commit)。而后面访问该数据块的的事务就先检查锁标志和对应的事务状态如果发现前面的事务没有提交并且要访问的数据记录被锁住了就被阻塞否则就清除相应的锁标志并提交自己的锁标志再重复以上动作。这就事延迟块清除。 如果大事务接触到了非常多的块并且到了缓冲区缓存的10%以上此时就会出现待清理的块并未由COMMIT操作清理即不是FAST COMMIT没有其它事务DML接触这些块而是SELECT一个表时就有可能出现ORA-1555的错误。 另外看到网上很多验证ORA-1555的错误实验都是用SELECT语句测试的但其实应该是“事务”或“查询”语句需要UNDO中数据时出现记录被覆盖的情况下都有可能报这个错因此开始介绍的夜维报错就是DELETE语句报的ORA-1555且这个夜维比较特殊的地方就是他是若干条(22条)DELETE语句在一个事务中即都执行完成后才一次COMMIT这样无形当中增加了事务的复杂度但凡其中一条语句等待则其他语句就无法提交也只能等待虽然这是由业务决定的但这种情况还是应该避免当然这是另一个话题了。 实例UNDO空间太小导致的ORA-1555。 创建一个2M大小不能自动扩展的UNDO空间。 SQL create undo tablespace undo_small datafile /opt/oracle/oradata/bisal/undo_small.dbf size 2m autoextend off; 将其设置为系统UNDO空间。 SQL alter system set undo_tablespace undo_small; System altered. 创建一张测试表。(注意这里使用dbms_random.random是为了将行弄乱使他们不至于认为有某种顺序从而得到随机的分布因为CTAS方式建表是力图按照查询获取的顺序将行放在块中。) SQL create table t as select * from all_objects order by dbms_random.random; Table created. 创建主键。 SQL alter table t add constraint t_undo_pk primary key(object_id); Table altered. 收集表的统计信息。 SQL exec dbms_stats.gather_table_stats(user, T, cascadetrue); PL/SQL procedure successfully completed. 重复更新表中所有数据。 SQL 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; / PL/SQL procedure successfully completed. 上述语句执行过程中创建查询语句这里使用DBMS_LOCK.SLEEP(0.01)来模拟查询单次时间是0.01秒由于是随机插入到表中的因此此处相当于随机地查询表中的块。这个查询语句执行几秒就可能失败。 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.01); l_rowcnt : l_rowcnt 1; end loop; close c; exception when others then dbms_output.put_line(rows fetched || l_rowcnt); raise; end; / (注报错 l_rowcnt number:0; * ERROR at line 8: ORA-06550: line 8, column 4: PLS-00103: Encountered the symbol L_ROWCNT when expecting one of the following: : ( ; not null range default character The symbol ; was substituted for L_ROWCNT to continue. 可能是l_object_name t.object_name%type少分号) 报错是 declare * ERROR at line 1: ORA-01555: snapshot too old: rollback segment number 11 with name _SYSSMU11$ too small ORA-06512: at line 21 总结 对于报错原因在于SELECT语句是按照object_id的索引进行读取(INDEX FULL SCAN)由于之前数据是按照随机顺序插入得到的因此此处是在全表上执行随机读这样就可能出现SELECT读到的数据可能是不同块中的此时UPDATE更新数据并提交标识UNDO中该记录可被覆盖由于UNDO空间较小因此出现SELECT读取的UNDO块被UPDATE更新、提交而被覆盖的可能性就会变大于是出现了ORA-1555的错误。 为了解决这种问题将UNDO设置为可扩展让Oracle自动管理UNDO可以最大幅度地扩展UNDO容量满足UNDO_RETENTION时间要求的同时也保证了SELECT可以读到的块不会被UPDATE提交所覆盖。 SQL column file_name new_val F SQL select file_name from dba_data_files where tablespace_nameUNDO_SMALL; FILE_NAME -------------------------------------------------------------------------------- /opt/oracle/oradata/bisal/undo_small.dbf SQL Alter database datafile F autoextend on 2 next 1m 3 maxsize 2048m; old 1: Alter database datafile F autoextend on new 1: Alter database datafile /opt/oracle/oradata/bisal/undo_small.dbf autoextend on Database altered. SQL select bytes/1024/1024 from dba_data_files where tablespace_nameUNDO_SMALL; BYTES/1024/1024 --------------- 4 此时再执行上述UPDATE和SELECT语句即可执行完成。 http://www.dengb.com/oracle/702397.htmlwww.dengb.comtruehttp://www.dengb.com/oracle/702397.htmlTechArticle现象 应用的夜维从夜里00:00开始执行但因为hang的原因(暂时猜测为夜维处理的某条数据和当前应用正常处理的某条数据相同出现前后...