所有由小潘发布的文章

喜欢分享的小潘.

Oracle ORA-01555快照过旧的错误(转载)

转载地址:http://blog.csdn.net/liaoyuanzi/article/details/7712682

关于Oracle ORA-01555快照过旧的错误


首先了解Oracle在什么情况下会产生ORA-01555错误: 


假设有一张6000万行数据的testdb表,预计testdb全表扫描1次需要2个小时,参考过程如下: 


1、在1点钟,用户A发出了select * from testdb;此时不管将来testdb怎么变化,正确的结果应该是用户A会看到在1点钟这个时刻的内容。


2、在1点30分,用户B执行了update命令,更新了testdb表中的第4100万行的这条记录,这时,用户A的全表扫描还没有到达第4100万条。毫无疑问,这个时候,第4100万行的这条记录是被写入了回滚段,假设是回滚段UNDOTS1,如果用户A的全表扫描到达了第4100万行,是应该会正确的从回滚段UNDOTS1中读取出1点钟时刻的内容的。 


3、这时,用户B将他刚才做的操作提交了,但是这时,系统仍然可以给用户A提供正确的数据,为那第4100万行记录的内容仍然还在回滚段UNDOTS1里,系统可以根据SCN到回滚段里找到正确的数据,但要注意到,这时记录在UNDOTS1里的第4100万行记录已经发生了重大的改变:就是第4100万行在回滚段UNDOTS1里的数据有可能随时被覆盖掉,为这条记录已经被提交了! 


4、由于用户A的查询时间漫长,而业务在一直不断的进行,UNDOTS1回滚段在被多个不同的transaction使用着,这个回滚段里的extent循环到了第4100万行数据所在的extent,由于这条记录已经被标记提交了,所以这个extent是可以被其他transaction覆盖掉的! 


5、到了1点45分,用户A的查询终于到了第4100万行,而这时已经出现了第4条说的情况,需要到回滚段UNDOTS1去找数据,但是已经被覆盖掉了,这时就出现了ORA-01555错误。 以上此段非本人原创 


 


分析:"报表"程序执行时间漫长,在程序查询的过程中其他用户对"报表"进行了更新,被更新的数据写入了回滚段,当程序到回滚段找数据时,发现数据已经被覆盖掉,于是就出现了ORA-01555错误。另外"报表"程序执行效率不高也会造成ORA-01555错误。
解决办法:
1、扩大回滚段,为回滚段是循环使用的,如果回滚段足够大,那么那些被提交的数据就能保存足够长的时间,使那些大事务完成一致性读取。之前EBS系统UNDO表空间为9GB,目前为10GB。见下图:



2、增加undo_retention时间,为UNDO回滚段是循环使用,里面的数据可能随时被循环覆盖掉,如果设置undo_retention时间更长,那么在retention规定的时间内,任何其他事务都不能覆盖这些数据。目前EBS系统undo_retention为10800秒(3个小时)。见下图:
 


3、最重要的一点就是优化程序相关查询语句,减少查询语句的一致性读,降低读取不到回滚段数据的风险。所有的出错信息都会纪录到数据库日志alert_PROD.log文件中,下图红线部分是一条SQL查询词句,ORA-01555很有可能是这条语句造成,把这条语句提供给开发人员来分析和优化程序代码。


————————————————————————————————————————–

ORA-01555 原与解决:

前面提到了ORA-01555错误,那么现在来看一下ORA-01555错误是怎样产生的。由于回滚段是循环使用的,当事务提交以后,该事务占用的回滚段事务会被标记为非活动,回滚段空间可以被覆盖重用。那么一个问题就出现了,如果一个查询需要使用被覆盖的回滚段构造前镜像实现一致性读,那么此时就会出现Oracle著名的ORA-01555错误。

ORA-01555错误的另外一个原为延迟块清除(Delayed Block Cleanout)。当一个查询触发延迟块清除时,Oracle需要去查询回滚段获得该事务的提交SCN,如果事务的前镜像信息已经被覆盖,并且查询SCN也小于回滚段中记录的最小提交SCN,那么Oracle将无从判断查询SCN和事务提交SCN的大小,此时出现延迟块清除导致的ORA-01555错误。

另外一种导致ORA-01555错误的情况出现在使用sqlldr直接方式加载(direct=true)数据时。当通过sqlldr direct=true 方式加载数据时,由于不产生重做和回滚信息,Oracle直接指定Cached Commit SCN 给加载数据,在访问这些数据时,有时会产生ORA-01555错误。

看下图的描述:假定在时间T用户A发出一条更新语句,更新SCOTT用户的SAL;用户B在Ty时间发出查询语句,查询SCOTT用户的SAL;用户A的更新在Tx时间提交,提交可能为快速提交块清除,也可能是延迟块清除;用户B的查询在Tz时间输出。

来看一下数据库在不同情况下的内部处理:

如果 Ty < T < Tz < Tx ,那么查询需要构造一致性读,由于事务尚未提交,可以通过回滚段构造前镜像,完成一致性读取。
·如果 Ty < T < Tx < Tz ,由于Ty查询时间小于T事务更新时间,那么数据库需要构造一致性读取,而Tz查询完成时间大于Tx提交时间,那么前镜像就有可能被覆盖,不可获取。

如果Tx的提交方式为Fast Block Cleanout,那么回滚段信息不可用时就会出现一致性读ORA-01555错误。

如果Tx的提交方式为Delayed Block Cleanout,那么回滚段信息不可用时Oracle将无法判断Ty和Tx的时间先后关系。如果 Ty > Tx ,那么Oracle可以正常进行块清除,并将块清除后的数据返回给用户B;如果 Ty < T ,那么Oracle需要继续构造一致性读返回给用户B;Oracle无法判断这两种情况,就会出现延迟块清除ORA-01555错误。

ORA-01555的直观解释是“snapshot too old”,也就是快照太旧,其根本含义就是查询需要的前镜像过于“久远”,已经无法找到了。可以想象,如果一个历时数个小时或十几个小时的查询,如果最后遭遇ORA-01555错误而失败,会是多么令人沮丧的一件事。一直以来,ORA-01555都是ORACLE最为头痛的问题之一。

在Oracle 9i的文档中这样描述ORA-01555错误:

01555, 00000, "snapshot too old: rollback segment number %s with name \"%s\" too small"
// *Cause: rollback records needed by a reader for consistent read are
//         overwritten by other writers
// *Action: If in Automatic Undo Management mode, increase undo_retention
//          setting. Otherwise, use larger rollback segments

可以看到,在Oracle 9i自动管理UNDO表空间模式下,UNDO_RETENTION参数的引入正是为了减少ORA-01555错误的出现。这个参数设置当事务提交之后(回滚段变得非活跃),回滚段中的前镜像数据在被覆盖前保留的时间,该参数以秒为单位,9iR1初始值为900秒,在Oracle 9iR2增加为10800秒。

显然该参数设置的越高就越能减少ORA-01555错误的出现,但是保留时间和存储空间是紧密相关的,如果UNDO表空间的存储空间有限,那么Oracle就会选择回收已提交事务占用的空间,置UNDO_RETENTION参数于不顾。

在Oracle 9i的AUM模式下,UNDO_RETENTION实际上是一个非担保(NO Guaranteed)限制。也就是说,如果有其他事务需要回滚空间,而空间出现不足时,这些信息仍然会被覆盖;从Oracle 10g开始,Oracle对于UNDO增加了Guarantee控制,也就是说,可以指定UNDO表空间必须满足UNDO_RETENTION的限制。当UNDO表空间设置为Guarantee,那么提交事务的回滚空间必须被保留足够的时间,如果UNDO表空间的空间不足,那么新的事务会空间不足而失败,而不是选择之前的覆盖。

从各个不同版本回滚段的管理变迁,我们可以看出Oracle一直在进步。

Oracle提供了一个内部事件(10203事件)可以用来跟踪数据库的块清除操作,10203事件可以通过以下命令设置,设置后需要重新启动数据库该参数方能生效:


 

alter system set event="10203 trace name context forever" scope=spfile;


 

需要注意的是,可能存在另外一种情况,就是当执行延迟块清除时,回滚段或原回滚表空间已经被删除,此时Oracle仍然可以通过字典表UNDO$来获得SCN信息,执行块清除。

关于Oracle的提交处理及块清除机制是一个极其复杂的过程,本文对这部分内容进行了适当简化说明,旨在使大家能够对Oracle的回滚机制、块清除机制有所了解。

– The End –

oracle ebs 解锁命令

以下是ebs解锁及相关辅助信息:

select (select ppf.full_name
          from per_people_f ppf, per_assignments_f paf, fnd_user fu
         where 1 = 1
           and ppf.person_id = paf.person_id
           and fu.employee_id = ppf.person_id
           and fu.user_name = vss.client_identifier
           and sysdate between ppf.effective_start_date and
               ppf.effective_end_date
           and sysdate between paf.effective_start_date and
               paf.effective_end_date
           and (fu.end_date is null or fu.end_date > sysdate)) user_name,
       (select fr.responsibility_name
          from fnd_responsibility_vl fr
         where fr.responsibility_key =
               (select substr(vss.action, instr(vss.action, '/') + 1)
                  from dual)) resp_name,
       (select fa.application_name
          from fnd_application_vl fa
         where fa.application_short_name =
               (select substr(vss.action, 1, instr(vss.action, '/')-1)
                  from dual)) prod_name,
       (select ff.user_form_name
          from fnd_form_vl ff
         where ff.form_name =
               (select substr(vss.module, instr(vss.module, ':', 1, 3) + 1)
                  from dual)) form_name,
       (select ff.description
          from fnd_form_vl ff
         where ff.form_name =
               (select substr(vss.module, instr(vss.module, ':', 1, 3) + 1)
                  from dual)) form_desc,
       dob.object_name table_name,
       vss.action action,
       vss.client_identifier user_code,
       vss.module,
       vss.machine,
       'alter system kill session ' || '''' || lo.session_id || ',' ||
       vss.serial# || ''';' kill_command,
       vss.osuser osuser,
       vss.process ap_pid,
       vps.spid db_pid,
       lo.locked_mode,
       lo.session_id,
       vss.serial#,
       vps.spid
  from v$locked_object lo, dba_objects dob, v$session vss, v$process vps
 where lo.object_id = dob.object_id
   and lo.session_id = vss.sid
   and vss.paddr = vps.addr
 order by resp_name asc, dob.object_name;

职责与配置文件的关系信息

select fpv.profile_option_value, fpv.level_value, fst.responsibility_name
  from fnd_profile_options fpo,
       fnd_profile_option_values fpv,
       fnd_profile_options_tl tl,
       fnd_responsibility_tl fst,
       (SELECT 10001 level_id, '地点' 文件安全性
          FROM dual
        UNION
        SELECT 10002 level_id, '应用产品' 文件安全性
          FROM dual
        UNION
        SELECT 10003 level_id, '责任' 文件安全性
          FROM dual
        UNION
        SELECT 10004 level_id, '用户' 文件安全性
          FROM dual
        UNION
        SELECT 10005 level_id, '服务器' 文件安全性
          FROM dual
        UNION
        SELECT 10006 level_id, '组织' 文件安全性 FROM dual) lv
 where 1 = 1
   and fpv.profile_option_id = fpo.profile_option_id
   and tl.language = 'ZHS'
   and fst.language = 'ZHS'
   and tl.profile_option_name = fpo.profile_option_name
      –and tl.user_profile_option_name like '%MO%业务实体%'
      –and fpo.profile_option_name = 'DEFAULT_ORG_ID'
   and fpo.profile_option_name = 'CUX_INV_ACCESS_SINV_CQC'
   and fpv.level_value = fst.responsibility_id
   and lv.level_id = fpv.level_id
–and fpv.level_value = fnd_global.resp_id
–and fpv.level_id = 10003 –职责层

 

–初始化环境


BEGIN


  fnd_global.apps_initialize(user_id      => 0,


                             resp_id      => 50658,


                             resp_appl_id => 20003);


  mo_global.set_policy_context(p_access_mode => 'S', p_org_id => 82);


  mo_global.init('SQLAP');


END;





–以下SQL查询当前配置的MO:安全性配置文件


SELECT *


  FROM per_security_profiles psp


 WHERE psp.security_profile_id =


 

       to_number(fnd_profile.value('XLA_MO_SECURITY_PROFILE_LEVEL'));

和fnd_profile.value('ORG_ID') 来配置




–以下SQL用来获取当前安全性配置文件和当前用户可访问的OU


SELECT hou.organization_id, hou.name


  FROM hr_operating_units hou


 WHERE hou.usable_flag IS NULL


   AND EXISTS


 (SELECT 1


          FROM per_organization_list per


         WHERE per.organization_id = hou.organization_id


           AND per.security_profile_id =


               to_number(fnd_profile.value('XLA_MO_SECURITY_PROFILE_LEVEL'))


        UNION


        SELECT 1


          FROM dual


         WHERE to_number(fnd_profile.value('ORG_ID')) = hou.organization_id)

 

 

表名:per_organization_list per, hr_operating_units hr

条件:WHERE per.security_profile_id(+) = to_number(fnd_profile.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL'))
AND hr.organization_id = per.organization_id(+)
AND hr.usable_flag is null
AND (EXISTS (SELECT 1
           FROM per_organization_list per1
          WHERE hr.organization_id = per1.organization_id
            AND per1.security_profile_id =
                to_number(fnd_profile.value('XLA_MO_SECURITY_PROFILE_LEVEL'))) OR
        fnd_profile.value('XLA_MO_SECURITY_PROFILE_LEVEL') = 0)

EBS客户相关信息查询

SELECT hou.name 业务实体,
       hp.party_name 客户名称,
       hca.account_number 客户编号,
       hp.tax_reference 纳税编号,
       hca.attribute1 客户集团,
       aa.status 有效否,
       to_char(bb.creation_date, 'YYYY-MM-DD') 创建日期,
       bb.bill_to_flag 收单标示,
       bb.ship_to_flag 收货标示,
       cc.country 国家,
       cc.address1 地点名称,
       dd.site_use_id 地点编号,
       dd.site_use_code,
       dd.primary_flag,
       dd.status,
       dd.location 业务目的编号,
       dd.bill_to_site_use_id 收单地id,
       rt.name 付款条件,
       gcc.concatenated_segments 应收科目,
       gcc01.concatenated_segments 收入科目,
       dd.tax_code 税码,
       (SELECT res.resource_name
          FROM jtf_rs_salesreps sr, jtf_rs_resource_extns_vl res
         WHERE sr.resource_id = res.resource_id
           AND sr.org_id = dd.org_id
           AND sr.salesrep_id = dd.primary_salesrep_id) 销售员
  FROM hz_parties               hp,
       hz_party_sites           aa,
       hz_cust_acct_sites_all   bb,
       hz_locations             cc,
       hz_cust_site_uses_all    dd,
       hr_operating_units       hou,
       ra_terms_vl              rt,
       hz_cust_accounts         hca,
       gl_code_combinations_kfv gcc,
       gl_code_combinations_kfv gcc01
 WHERE aa.party_site_id = bb.party_site_id
   AND hca.party_id = hp.party_id
   AND aa.status = 'A'
   AND rt.term_id = dd.payment_term_id
   AND hou.organization_id = bb.org_id
   AND hp.party_id = aa.party_id
   AND aa.location_id = cc.location_id
   AND bb.cust_acct_site_id(+) = dd.cust_acct_site_id
   AND dd.status <> 'I'
   AND gcc.code_combination_id(+) = dd.gl_id_rec
   AND gcc01.code_combination_id(+) = dd.gl_id_rev
      –AND hou.name = 'OU'
      –条件1:客户对应的OU,选择目标OU
   AND to_char(bb.creation_date, 'yyyy-mm-dd') >= '2000-01-01'
      –条件2:供应商创建对应的起始日期,选择创建日期范围,如不需限制,请注释该条件
 —  AND to_char(bb.creation_date, 'yyyy-mm-dd') <= '2015-12-08'
–条件2:供应商创建对应的截止日期,选择创建日期范围,如不需限制,请注释该条件

NVARCHAR 和VARCHAR区别和使用

1、各自的定义:

       ► nvarchar(n):包含n个字符的可变长度Unicode字符数据。n的值必须介于1与4,000之间。字节的存储大小是所输入字符个数的两倍。所输入的数据字符长度可以为零。 

       ► varchar[(n)]:长度为n个字节的可变长度且非Unicode的字符数据。n 必须是一个介于1和8,000之间的数值。存储大小为输入数据的字节的实际长度,而不是n个字节。所输入的数据字符长度可以为零。

varchar(max)最大2gb字符 使用C#中的DbType.varchar针对max DbType.varchar,-1

2、区别:

      ► 从存储方式上,nvarchar是按字符存储的,而 varchar是按字节存储的;

      ► 从存储量上考虑,varchar比较节省空间,因为存储大小为字节的实际长度,而 nvarchar是双字节存储;

      ► 在使用上,如果存储内容都是英文字符而没有汉字等其他语言符号,建议使用varchar;含有汉字的使用nvarchar,因为nvarchar是使用Unicode编码,即统一的字符编码标准,会减少乱码的出现几率;

      ►如果你做的项目可能涉及不同语言之间的转换,建议用nvarchar。

这点要注意:varchar适合与存储英文和数字;nvarchr一般用于存储中文或其他语言的输入,因为这样,可以防止到其他语言平台上出现乱码的问题。

举个例子: 
create table a (name1 varchar(8)) 
insert a select '张红a' 
–存储长度为5个字节 
insert a select '王一南' 
–存储长度为6个字节

–意思是varchar变长字符数据类型与存储数据的实际长度是一致的 

nvarchar(n):可变长度 Unicode 数据,其最大长度为 4,000 字符。 
字节的存储大小是所输入字符个数的两倍, 
就是说它是双字节来存储数据的。 
如果存储数据如果存在单字节时,它也是以双字节来占用存储空间的。 

举个例子: 
create table aa (name1 nvarchar(8)) 
insert aa select '张红a' 
–存储长度为6个字节

摘自:http://blog.csdn.net/feixianxxx/article/details/4454659