表dml操作权限授权给public,导致只读用户失效

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:表dml操作权限授权给public,导致只读用户失效

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

最近一个客户和我反馈,他们创建了一个只读用户(之时给了create session和select表权限),但是其中有部分表可以执行dml操作,我登录系统进行确认

SQL> SELECT PRIVILEGE, ADMIN_OPTION
  2    FROM DBA_SYS_PRIVS
  3   WHERE GRANTEE =  'ALL_READONLY'
  4  UNION
  5  SELECT PRIVILEGE, ADMIN_OPTION
  6    FROM ROLE_SYS_PRIVS
  7   WHERE ROLE IN
  8         (SELECT GRANTED_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE =  'ALL_READONLY')
  9  UNION
 10  SELECT PRIVILEGE, ADMIN_OPTION
 11    FROM ROLE_SYS_PRIVS
 12   WHERE ROLE IN (SELECT GRANTED_ROLE
 13                    FROM ROLE_ROLE_PRIVS
 14                   WHERE ROLE IN (SELECT GRANTED_ROLE
 15                                    FROM DBA_ROLE_PRIVS
 16                                   WHERE GRANTEE = 'ALL_READONLY'));

PRIVILEGE                                ADM
---------------------------------------- ---
CREATE SESSION                           NO

尝试对一个表做dml操作,确实可以对u1.t1表进行dml操作

SQL> conn all_readonly/PASSWORD
Connected.
SQL> update U1.T1 set SNAME='111_test' where sid='www.xifenfei.com';

1 row updated.

SQL> rollback;

Rollback complete.

查看这个表的相关授权,关于all_readonly(只读用户)的授权,也确实只是授权了查询权限

SQL>  SELECT GRANTEE,PRIVILEGE,OWNER,TABLE_NAME  FROM dba_TAB_PRIVS WHERE TABLE_NAME ='T1' and GRANTEE='ALL_READONLY'

GRANTEE              PRIVILEGE                                OWNER                TABLE_NAME
-------------------- ---------------------------------------- -------------------- --------------------
ALL_READONLY         SELECT                                   U1                    T1

既然t1这个表可以被dml操作,那是这个表是否还有其他授权,进一步查询该表授权(不限于ALL_REAONLY用户)

SQL> SELECT GRANTEE,PRIVILEGE,OWNER,TABLE_NAME  FROM dba_TAB_PRIVS WHERE TABLE_NAME ='T1';

GRANTEE              PRIVILEGE                                OWNER                TABLE_NAME
-------------------- ---------------------------------------- -------------------- --------------------
PUBLIC               ALTER                                    U1                    T1
PUBLIC               DELETE                                   U1                    T1
PUBLIC               INDEX                                    U1                    T1
PUBLIC               INSERT                                   U1                    T1
PUBLIC               SELECT                                   U1                    T1
PUBLIC               UPDATE                                   U1                    T1
PUBLIC               REFERENCES                               U1                    T1
PUBLIC               ON COMMIT REFRESH                        U1                    T1
PUBLIC               QUERY REWRITE                            U1                    T1
PUBLIC               DEBUG                                    U1                    T1
PUBLIC               FLASHBACK                                U1                    T1
ALL_READONLY         SELECT                                   U1                    T1

14 rows selected.

这下明确了,由于授权了u1.t1表的(insert,delete,update等)权限给public,导致其他用户也可以对这些表进行授权给public的所有操作.
不管任何原因,都不建议授权表/对象的操作给public,这样会导致登录该数据库的所有用户都具有这个权限,风险不可控

当前主流数据库版本服务支持周期-202503

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:当前主流数据库版本服务支持周期-202503

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

在最新的”当前数据库版本的发行时间表 (Doc ID 1626244.1)”文档中,oracle官方更新的数据库产品的支持周期,最重要的一点就是oracle 19c标准服务延期到2029年12月31日
DBROADMAP12-2-2024

版本 补丁结束日期 注意和例外
 23ai

Long Term Release

Premier Support – 2032年12月31日

Extended Support - 时间待定

  • 由于此次发布中突破性人工智能技术的重要性,我们将其从 Oracle 数据库 23c 重新命名为 Oracle 数据库 23ai
  • 现在可在云上、Oracle Exadata 和 Oracle Database Appliance 中使用。请参阅下方的 Oracle 数据库日程表中的详细信息
  • Premier Support将于 2031 年 12 月 31 日结束
  • 通过扩展支持或者ULA进行错误修正/补丁的截止日期待定
21c

Innovation Release

 2027年7月31日
  • 错误更正/补丁 有效期至2027年7月31日
  • 21c没有资格申请 Extended Support(ES)
  • 21c只提供 Release Updates (RUs) 补丁
  • 21c不适用于Exadata Database Service

 

19c

Long Term Release

2029年12月31日,没有ES/ULA

2032年12月31日,有ES/ULA

 

  • Premier Support(PS)将于2029年12月31日结束。扩展支持(ES)将从2030年1月1日持续到2032年12月31日。
  • 错误更正/补丁,付费的ES可到2032年12月31日;没有付费的ES,有效期到2029年12月31日
  • 从 2022 年 10 月的补丁周期开始,19.17.0 及更高版本将不再提供 19c RUR。在 2023 年 1 月交付 Oracle Database 19c RUR 19.16.2 之后,不会在任何平台上交付额外的 RUR。更多细节请参考文档 Sunsetting of 19c RURs and FAQ (Doc ID 2898381.1))
  • 为了让客户更频繁地访问推荐和经过良好测试的补丁集合,Oracle 从 2022 年 11 月开始推出 Monthly Recommended Patches (MRP)。 MRP 仅支持 Linux x86-64 平台。(更多细节请参考文档 Introducing Monthly Recommended Patches (MRPs) and FAQ (Doc ID 2898740.1))
18c

Innovation Release

 

2021年6月30日
  • 错误更正/补丁 有效期至2021年6月30日,18c已进入 Sustaining Support 阶段。
  • 18c没有资格申请 Extended Support(ES)
  • 18c 在 Exadata Database Service、Base Database Service 或 Exadata Cloud@Customer 上不受支持。
12.2.0.1

 

2022年3月31日

Upgrade Support (Restricted Availability) Jan 1, 2024- Dec 31, 2025 - 具体请联系 CSS

  • 这个版本的错误更正/补丁已经结束
  • 12.2.0.1 没有资格申请 Extended Support(ES)
  • 在 Exadata Database Service、Base Database Service 或 Exadata Cloud@Customer 上运行 12.2.0.1 需要购买 Upgrade Support (Restricted Availability)(旧称MDS) 服务
12.1.0.2

最终版本

2022年7月31日,有付费的ES, ULA, 或者减免费用的 EBS

Dec 31, 2025 (Upgrade Support (Restricted Availability)- 具体请联系 CSS)

  • 这个版本的错误更正/补丁已经结束
  • Premier Support(PS)截止至2018年7月31日,为期一年的免费 Extended Support(ES)有效期至2019年7月31日
  • 从 2019年8月1日 至 2022年7月31日,需要ES费用或ULA. 没有付费的 ES or ULA, 补丁截止于 2019年7月31日
  • 我们为电子商务客户提供全球ES uplift 费用减免,详情和到期日期见: Extended Support Fee Waiver for Oracle Database 12.1 and 11.2 for Oracle E-Business Suite (Doc ID 2522948.1) 或技术支持政策文件
  • Apple Macintosh 平台 补丁结束日期为2021年7月31日 
  • 微软Windows平台: 对于 12.1.0.2 Database, Oracle 在 Microsoft Windows 2008 上运行 12.1.0.2 Database。 这个平台的 end-of-life support 是 January 14, 2020。 甲骨文做出了合理的努力,在2022年7月之前为Windows上的数据库12.1.0.2提供补丁,但这种支持已经过期。
  • 在 Exadata Database Service、Base Database Service 或 Exadata Cloud@Customer 上运行 12.1.0.2 需要购买 Upgrade Support (Restricted Availability)(旧称MDS) 服务
12.1.0.1 2016年8月31日
  • 这个版本的错误更正/补丁已经结束
  • 12.1.0.1 没有资格申请 Extended Support (ES)
  • 12.1.0.1 是 Standard Edition (SE) 和 Standard Edition One (SE1) 的最后一个版本
11.2.0.4

最终版本 for 11.2

  • 2020年12月31日(有偿扩展支持 或 ULA扩展支持 或 减免费用的EBS)
  • 2025年12月31日(Upgrade Support (Restricted Availability) - 具体请联系 CSS)
  • 2021年12月31日 适用于OpenVMS平台

 

  • Premier Support (PS)截止到2015年1月31日,而为期一年的免费Extended Support(ES)持续到2018年12月31日。
  • 从2019年1月1日开始到2020年12月31日,将需要ES费用或ULA。
  • Oracle为电子商务客户提供全球ES uplift 费用减免,详情和到期日期见: Extended Support Fee Waiver for Oracle Database 12.1 and 11.2 for Oracle E-Business Suite (Doc ID 2522948.1) 或技术支持政策文件。
  • 第1代 ExaCC, OCC DBCS, and ODA 将拥有额外3个月的支持周期. 这些平台上的数据库的支持周期截止到: 2021年3月31日。可以创建新实例,直到扩展支持终止为止。但是,Oracle不承诺在支持终止后任何11.2.0.4 DBCS实例将继续运行。
  • 市场驱动支持(Market Driven Support)提供以下数据库云服务:第1代和第2代ExaCC,OCC DBCS,OCI DBCS,OCI ExaCS。 直到市场驱动支持终止(2021年12月31日),可以创建新实例。 Oracle不承诺在Upgrade Support(旧称MDS)支持终止后任何11.2.0.4 DBCS实例将继续运行。 市场驱动支持不适用于PSM-based OCI DBCS,OCI-C DBCS和OCI-C ExaCS。
  • 在 Exadata Database Service、Base Database Service 或 Exadata Cloud@Customer 上运行 11.2.0.4 需要购买 Upgrade Support (Restricted Availability)(旧称MDS) 服务
  • 11.2.0.4是OpenVMS上的最终版本。 在2021日历年中,除了标准的专业支持费用之外无需其他费用,客户能够收到重要度1的修复程序和安全更新。涵盖范围不包括新认证,第三方产品或任何Java/JDK功能(包括数据库中嵌入的Java组件)。涵盖范围还不包括与加密和网络加密有关的任何更新。 此供应不包括标准的安全补丁更新(SPU)。

 


aix磁盘损坏oracle数据库恢复

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:aix磁盘损坏oracle数据库恢复

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

客户aix环境硬盘异常导致系统无法启动,初步判断是数据文件存放在本地磁盘的空间中(本地两个盘都异常,系统无法启动),通过硬件恢复厂商镜像出来,但是通过aix文件系统直接挂载提示需要fsck,但是做fsck之后,提示大量文件丢失(最关键的数据文件和备份文件都被自动删除)
dmp-remove
fsck-remove


基于这种情况,采用镜像主机挂载的方式肯定不行,考虑直接采用软件直接解析,能够看到软件,可惜由于大量的文件系统元数据损坏,解析出来的数据文件和dmp也不可用(大量损坏和空块)
QQ20250307-122939

基于上述情况,只能采用碎片级别恢复出来数据文件
QQ20250307-123123

然后使用dul工具把数据恢复到表中,实现最大限度抢救客户数据
QQ20250307-123653

对于数据库级别恢复,这个是理论上的终极恢复方法

使用sid方式直接访问pdb(USE_SID_AS_SERVICE_LISTENER)

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:使用sid方式直接访问pdb(USE_SID_AS_SERVICE_LISTENER)

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

有些应用,因为特殊原因,需要通过sid来访问数据库,在pdb环境中原则上都是通过服务名访问的,可以通过一定的监听配置实现使用pdb名的sid来访问该pdb
在pdb0中创建u_test用户并授权

[oracle@ora19c:/u01/app/oracle/product/19.3.0/db/network/admin]$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Mon Feb 17 22:01:54 2025
Version 19.24.0.0.0

Copyright (c) 1982, 2024, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.24.0.0.0

sys@ORA19C 22:01:54> show pdbs;

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB0                           READ WRITE NO
         4 PDBXXX                         MOUNTED
sys@ORA19C 22:01:56> alter session set container=pdb0;

Session altered.

Elapsed: 00:00:00.16
sys@ORA19C 22:02:07> create user u_test identified by oracle;

User created.

Elapsed: 00:00:00.29
sys@ORA19C 22:02:21> grant dba to u_test;

Grant succeeded.

Elapsed: 00:00:00.01

监听的配置和状态

[oracle@ora19c:/home/oracle]$ cat /u01/app/oracle/product/19.3.0/db/network/admin/listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/19.3.0/db/network/admin/listener.ora
# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )



[oracle@ora19c:/home/oracle]$ lsnrctl status

LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 17-FEB-2025 22:07:12

Copyright (c) 1991, 2024, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ora19c)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
Start Date                17-FEB-2025 22:06:39
Uptime                    0 days 0 hr. 0 min. 32 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/oracle/product/19.3.0/db/network/admin/listener.ora
Listener Log File         /u01/app/oracle/diag/tnslsnr/ora19c/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=ora19c)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
Services Summary...
Service "21b067cbda1dbcd4e0630100007f12b6" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "22394b20557aff3ee0630100007fafe0" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "86b637b62fdf7a65e053f706e80a27ca" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "ora19c" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "ora19cXDB" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "pdb0" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "pdbxxx" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
The command completed successfully

创建pdb0基于服务和sid的tns(pdb0,pdb0_sid)

[oracle@ora19c:/u01/app/oracle/product/19.3.0/db/network/admin]$ cat tnsnames.ora
pdb0 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = pdb0)
    )
  )
pdb0_sid =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (sid = pdb0)
    )
  )

[oracle@ora19c:/u01/app/oracle/product/19.3.0/db/network/admin]$ tnsping pdb0

TNS Ping Utility for Linux: Version 19.0.0.0.0 - Production on 17-FEB-2025 22:03:00

Copyright (c) 1997, 2024, Oracle.  All rights reserved.

Used parameter files:
/u01/app/oracle/product/19.3.0/db/network/admin/sqlnet.ora


Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c)(PORT = 1521)) 
(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = pdb0)))
OK (0 msec)
[oracle@ora19c:/u01/app/oracle/product/19.3.0/db/network/admin]$ tnsping pdb0_sid

TNS Ping Utility for Linux: Version 19.0.0.0.0 - Production on 17-FEB-2025 22:03:10

Copyright (c) 1997, 2024, Oracle.  All rights reserved.

Used parameter files:
/u01/app/oracle/product/19.3.0/db/network/admin/sqlnet.ora


Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c)(PORT = 1521))
 (CONNECT_DATA = (SERVER = DEDICATED) (sid = pdb0)))
OK (0 msec)

分别测试pdb0和pdb0_sid访问数据库
测试证明基于服务名的方式可以正常访问pdb,基于sid的方式无法访问pdb

[oracle@ora19c:/home/oracle]$ sqlplus u_test/oracle@pdb0

SQL*Plus: Release 19.0.0.0.0 - Production on Mon Feb 17 22:08:35 2025
Version 19.24.0.0.0

Copyright (c) 1982, 2024, Oracle.  All rights reserved.

Last Successful login time: Mon Feb 17 2025 22:06:11 +08:00

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.24.0.0.0

u_test@PDB0 22:08:35> exit
Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.24.0.0.0
[oracle@ora19c:/home/oracle]$ sqlplus u_test/oracle@pdb0_sid

SQL*Plus: Release 19.0.0.0.0 - Production on Mon Feb 17 22:08:39 2025
Version 19.24.0.0.0

Copyright (c) 1982, 2024, Oracle.  All rights reserved.

ERROR:
ORA-12505: TNS:listener does not currently know of SID given in connect
descriptor


Enter user-name: 
ERROR:
ORA-01017: invalid username/password; logon denied


Enter user-name: 
ERROR:
ORA-01017: invalid username/password; logon denied


SP2-0157: unable to CONNECT to ORACLE after 3 attempts, exiting SQL*Plus

在listener.ora中增加USE_SID_AS_SERVICE_LISTENER = ON,并reload加载
注意:USE_SID_AS_SERVICE_LISTENER 中的LISTENER根据不同的监听名字而发生改变

[oracle@ora19c:/home/oracle]$ cat /u01/app/oracle/product/19.3.0/db/network/admin/listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/19.3.0/db/network/admin/listener.ora
# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )
USE_SID_AS_SERVICE_LISTENER = ON

[oracle@ora19c:/home/oracle]$ lsnrctl reload

LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 17-FEB-2025 22:12:13

Copyright (c) 1991, 2024, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ora19c)(PORT=1521)))
The command completed successfully

[oracle@ora19c:/home/oracle]$ lsnrctl status

LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 17-FEB-2025 22:13:05

Copyright (c) 1991, 2024, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ora19c)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
Start Date                17-FEB-2025 22:06:39
Uptime                    0 days 0 hr. 6 min. 26 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/oracle/product/19.3.0/db/network/admin/listener.ora
Listener Log File         /u01/app/oracle/diag/tnslsnr/ora19c/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=ora19c)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
Services Summary...
Service "21b067cbda1dbcd4e0630100007f12b6" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "22394b20557aff3ee0630100007fafe0" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "86b637b62fdf7a65e053f706e80a27ca" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "ora19c" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "ora19cXDB" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "pdb0" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
Service "pdbxxx" has 1 instance(s).
  Instance "ora19c", status READY, has 1 handler(s) for this service...
The command completed successfully

尝试tns名字为pdb0和pdb0_sid名字登录数据库
在listener.ora文件中设置了USE_SID_AS_SERVICE_LISTENER = ON之后,基于sid的方式可以直接访问pdb

[oracle@ora19c:/home/oracle]$ sqlplus u_test/oracle@pdb0_sid

SQL*Plus: Release 19.0.0.0.0 - Production on Mon Feb 17 22:12:16 2025
Version 19.24.0.0.0

Copyright (c) 1982, 2024, Oracle.  All rights reserved.

Last Successful login time: Mon Feb 17 2025 22:08:35 +08:00

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.24.0.0.0

u_test@PDB0 22:12:16> exit
Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.24.0.0.0
[oracle@ora19c:/home/oracle]$ sqlplus u_test/oracle@pdb0

SQL*Plus: Release 19.0.0.0.0 - Production on Mon Feb 17 22:12:28 2025
Version 19.24.0.0.0

Copyright (c) 1982, 2024, Oracle.  All rights reserved.

Last Successful login time: Mon Feb 17 2025 22:12:16 +08:00

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.24.0.0.0

u_test@PDB0 22:12:28> 

ORA-600 [4000] [a]相关bug

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:ORA-600 [4000] [a]相关bug

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

ORA-600 [4000 ] [a]一般是这样的报错格式,其中[a] Undo segment number,类似错误主要bug以及对应的修复版本列表

Bug Fixed Description
26966120 18.18, 18.3, 19.1 PDML workload reports ORA-7445 [kdmsfree] / ORA-00600 [4000]
16761566 11.2.0.3.9, 11.2.0.3.BP22, 11.2.0.4, 12.1.0.2, 12.2.0.1 Instance fails to start with ORA-600 [4000] [usn#]
13910190 11.2.0.3.BP15, 11.2.0.4, 12.1.0.1 ORA-600 [4000] from plugged in tablespace in Exadata
37173201 Hitting ORA-600 [4000] during shutdown
36440495 19.26 SECURE FILE LOB CAUSING ORA-00600:[4000]
34547607 19.23, 23.4 [TXN MGMT LOCAL] ORA-600 [ktugct: corruption detected] w/ Compression & RAC DB Instances Crash
32800248 19.24, 23.4 DB:DISTRIB: Avoid ORA-600[4000]/ORA-600[4097] in the DB background RECO scenario.
35143304 19.24 consider converting ORA-600 [4000] to pdb-specific assert or soft assert
33343993 19.16 Convert ORA-600 [4000] to PDB Specific Assert and Crash Only the Affected PDB
32156194 19.12 ORA-600 [25027] during the select on x$ktcxb
32765471 aim:ORA-600 [4000] – kccpb_sanity_check
23030488 18.1 ORA-00600 [4000] During First Open of PDB After Undo Mode Switch
22610979 18.1 ORA-00600 [4000] On DB Close of STANDBY Due to MMON Process
21770222 12.2.0.1 ORA-600: [4000] in CDB
21379969 12.2.0.1 ORA-00600 [4000] after a tablespace is transported and plugged into another DB
20427315 12.2.0.1 ORA-600 [4000] While Performing DMLs In Freelist Segment
20407770 12.2.0.1 ORA-00600 [4000] error in CDB and DDL operations in PDBs
19352922 12.2.0.1 IMC: ORA-600[4000] may occur on HCC block
14741727 11.2.0.2.9, 11.2.0.2.BP19, 11.2.0.3.BP12, 11.2.0.3.BP13, 11.2.0.4, 12.1.0.1 Fixes for bug 12326708 and 14624146 can cause problems – backout fix
12619529 11.2.0.3.BP18, 11.2.0.4, 12.1.0.1 ORA-600[kdsgrp1] from SELECT on plugged in tablespace with FLASHBACK
10425010 11.2.0.3, 12.1.0.1 Stale data blocks may be returned by Exadata FlashCache
9145541 11.1.0.7.4, 11.2.0.1.2, 11.2.0.2, 12.1.0.1 OERI[25027]/OERI[4097]/OERI[4000]/ORA-1555 in plugged datafile after CREATE CONTROLFILE in 11g
12353983 11.2.0.1 ORA-600 [4000] with XA in RAC
7687856 11.2.0.1 ORA-600 [4000] from DML on transported ASSM tablespace
2917441 11.1.0.6 OERI [4000] during startup
3115733 9.2.0.5, 10.1.0.2 OERI[4000] / index corruption can occur during index coalesce
2959556 9.2.0.5, 10.1.0.2 STARTUP after an ORA-701 fails with OERI[4000]
1371820 8.1.7.4, 9.0.1.4, 9.2.0.1 OERI:4506 / OERI:4000 possible against transported tablespace
434596 7.3.4.2, 8.0.3.0 ORA-600[4000] from altering storage of BOOTSTRAP$

如何判断数据文件是否处于begin backup状态

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:如何判断数据文件是否处于begin backup状态

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

在数据库恢复中,经常会遇到由于某种原因对数据库执行了begin backup,但是没有执行end backup,然后导致库无法启动的例子,那么怎么判断当前的库是存在这种情况呢?有两种方法可以对其进行判断:
1. 通过查询v$backup表来确认

SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE    11.2.0.4.0      Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

SQL> select * from v$backup;

     FILE# STATUS                CHANGE# TIME
---------- ------------------ ---------- ------------
         1 NOT ACTIVE         1.1210E+12 09-FEB-25
         2 NOT ACTIVE         1.1210E+12 04-JAN-25
         3 NOT ACTIVE         1.1210E+12 09-FEB-25
         4 NOT ACTIVE         1.1210E+12 09-FEB-25

SQL> alter tablespace users begin backup;

Tablespace altered.

SQL>  select * from v$backup;

     FILE# STATUS                CHANGE# TIME
---------- ------------------ ---------- ------------
         1 NOT ACTIVE         1.1210E+12 09-FEB-25
         2 NOT ACTIVE         1.1210E+12 04-JAN-25
         3 NOT ACTIVE         1.1210E+12 09-FEB-25
         4 ACTIVE             1.1210E+12 09-FEB-25

SQL>  alter tablespace users end backup;

Tablespace altered.

SQL> select * from v$backup;

     FILE# STATUS                CHANGE# TIME
---------- ------------------ ---------- ------------
         1 NOT ACTIVE         1.1210E+12 09-FEB-25
         2 NOT ACTIVE         1.1210E+12 04-JAN-25
         3 NOT ACTIVE         1.1210E+12 09-FEB-25
         4 NOT ACTIVE         1.1210E+12 09-FEB-25

v$backup.status=’ACTIVE’表示该文件处于begin backup状态

2. 通过bbed查看kcvfh.kcvfhsta值
确认所有数据文件都没有处于begin backup状态

SQL> select * from v$backup;

     FILE# STATUS                CHANGE# TIME
---------- ------------------ ---------- ------------
         1 NOT ACTIVE         1.1210E+12 09-FEB-25
         2 NOT ACTIVE         1.1210E+12 04-JAN-25
         3 NOT ACTIVE         1.1210E+12 09-FEB-25
         4 NOT ACTIVE         1.1210E+12 09-FEB-25

list内容列表

[oracle@iZbp11c0qyuuo1gr7j98upZ ~]$ cat /home/oracle/list.txt 
         1 /u01/app/oracle/oradata/xifenfei/system01.dbf
         2 /u01/app/oracle/oradata/xifenfei/sysaux01.dbf
         3 /u01/app/oracle/oradata/xifenfei/undotbs01.dbf
         4 /u01/app/oracle/oradata/xifenfei/users01.dbf

bbed查看kcvfh.kcvfhsta值

[oracle@iZbp11c0qyuuo1gr7j98upZ ~]$ bbed listfile=/home/oracle/list.txt
Password: 

BBED: Release 2.0.0.0.0 - Limited Production on Sun Feb 9 21:20:15 2025

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

************* !!! For Oracle Internal Use only !!! ***************

BBED> set file 1
        FILE#           1

BBED> p kcvfh.kcvfhsta
ub2 kcvfhsta                                @138      0x2004 (KCVFHOFZ)

BBED> set file 2
        FILE#           2

BBED> p kcvfh.kcvfhsta
ub2 kcvfhsta                                @138      0x0004 (KCVFHOFZ)

BBED> set file 3
        FILE#           3

BBED> p kcvfh.kcvfhsta
ub2 kcvfhsta                                @138      0x0004 (KCVFHOFZ)

BBED> set file 4
        FILE#           4

BBED> p kcvfh.kcvfhsta
ub2 kcvfhsta                                @138      0x0004 (KCVFHOFZ)

执行database begin backup

SQL> alter database begin backup;

Database altered.

SQL> select * from v$backup;

     FILE# STATUS                CHANGE# TIME
---------- ------------------ ---------- ------------
         1 ACTIVE             1.1210E+12 09-FEB-25
         2 ACTIVE             1.1210E+12 09-FEB-25
         3 ACTIVE             1.1210E+12 09-FEB-25
         4 ACTIVE             1.1210E+12 09-FEB-25

再次bbed查看kcvfh.kcvfhsta值

BBED> set file 1
        FILE#           1

BBED> p kcvfh.kcvfhsta
ub2 kcvfhsta                                @138      0x2001 (KCVFHHBP)

BBED> set file 2
        FILE#           2

BBED>  p kcvfh.kcvfhsta
ub2 kcvfhsta                                @138      0x0001 (KCVFHHBP)

BBED> set file 3
        FILE#           3

BBED>  p kcvfh.kcvfhsta
ub2 kcvfhsta                                @138      0x0001 (KCVFHHBP)

BBED> set file 4
        FILE#           4

BBED>  p kcvfh.kcvfhsta
ub2 kcvfhsta                                @138      0x0001 (KCVFHHBP)

对于非system文件kcvfh.kcvfhsta=0×0001表示begin backup状态
对于system文件kcvfh.kcvfhsta=0×2001表示begin backup状态

_gc_undo_affinity=FALSE触发ORA-01558

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:_gc_undo_affinity=FALSE触发ORA-01558

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

最近有客户遭遇非系统回滚段报ORA-01558的故障,类似:ORA-01558: out of transaction ID’s in rollback segment _SYSSMU4_1254879796$,在之前的恢复case中遇到两次system rollback报ORA-01558而不能正常启动的案例.(ORA-01092 ORA-00604 ORA-01558故障处理ORA-01558: out of transaction ID’s in rollback segment SYSTEM),这次是业务回滚段,出来起来相对比较简单,直接重建该回滚段所在undo表空间即可.遭遇该问题的主要原因是由于19c rac中由于禁用drm,设置了_gc_undo_affinity=FALSE参数导致.
gc_undo_affinity_ora-1558


还有一个类似bug,需要注意:Bug 19700135 ORA-600 [4187] when the undo segment wrap# is close to the max value of 0xffffffff,主要影响版本为:
1

关于该bug的描述

ORA-600 [4187] can occur for undo segments where wrap# is close to the max value of 0xffffffff (KSQNMAXVAL).
This normally affects databases with high transaction rate that have existed for a relatively long time.
 
To identify undo segments causing the above error and others that may potentially cause it 
in the future, run the next query:
 
 select b.segment_name, b.tablespace_name 
         ,a.ktuxeusn "Undo Segment Number"
         ,a.ktuxeslt "Slot"
         ,a.ktuxesqn "Wrap#"
   from  x$ktuxe a, dba_rollback_segs b
   where a.ktuxesqn > -429496730 and a.ktuxesqn < 0
       and a.ktuxeusn = b.segment_id;
 
Then drop the undo segments or the undo tablespace from the output above.
 
With this fix in place an error ORA-1558 is eventually produced for the affected undo segment
which still requires dropping the undo segment:
  ORA-1558 "out of transaction ID's in rollback segment %s"
   Cause: All the available transaction id's have been used
   Action: Shutdown the instance and restart using other rollback segment(s),
                then drop the rollback segment that has no more transaction id's.

public授权语句

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:public授权语句

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

在上一篇文章中写到数据泵迁移导致sys授权丢失(impdp导入数据丢失sys授权问题分析),这次进一步完善在有些系统中,会出现对部分权限授权给public的操作,使用逻辑方式(exp/imp,expdp/impdp)进行迁移,可能会导致这个部分权限丢失,从而使得系统部分功能异常,可以通过类似sql查询出来授权语句,在新库上执行

select 'grant ' || privilege || ' on ' || '"' || OWNER || '"."' ||
       table_name || '"' || ' to ' || grantee || ';' "GRANTS"
  from dba_tab_privs
 where privilege not in ('READ', 'WRITE')
   and table_name not like '%/%'
   and owner not in ('SYSTEM',
                     'WMSYS',
                     'XDB',
                     'CTXSYS',
                     'MDSYS',
                     'EXFSYS',
                     'APEX_030200',
                     'ORDSYS',
                     'ORDPLUGINS',
                     'DBSNMP',
                     'OLAPSYS',
                     'ORDDATA')
   and grantee in ('PUBLIC')
 order by 1;

中文环境显示AR8MSWIN1256(阿拉伯语字符集)

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:中文环境显示AR8MSWIN1256(阿拉伯语字符集)

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

最近恢复了一个阿拉伯语的Oracle数据库,参见案例:.pzpq扩展名勒索恢复,在客户验证数据的环节,出现了阿拉伯语显示乱码的问题.通过几个方法进行了验证,确认数据恢复没有问题
1. 通过dul工具对于有阿拉伯语的表恢复成文本文件,然后使用阿拉伯编码进行查看(可以正常显示阿拉伯语)
dul-alb


2. 在cmd中设置编码为阿拉伯编码,nls_lang也设置和数据库一致(可以正常显示阿拉伯语)[在win 10 系统中此方法可行,2003 系统依然显示有乱码]
AR8MSWIN1256

chcp-1256

win 10 操作系统显示
alb

win 2003操作系统显示
2003

3.设置了在cmd中设置NLS_LANG=american_america.AR8MSWIN1256,然后启动plsql dev(无法正常显示阿拉伯语【乱码】)
plsql-dev

目前没有找到有效方式使得plsql dev在中文操作系统环境中正常显示阿拉伯语,后续继续关注该问题,如果有新发现及时更新

处理 Oracle 块损坏

联系:手机/微信(+86 17813235971) QQ(107644445)QQ咨询惜分飞

标题:处理 Oracle 块损坏

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

本文章介绍了许多类型的错误,很多其他地方也可能引用到本文章。重要的是,您需要知道关于每个坏块的以下信息:

  • 包含坏块的文件的绝对文件编号 (FILE NUMBER)。
    本文中称为“&AFN”。
  • 包含坏块的文件的名称。
    本文中称为“&FILENAME”。
    如果您知道文件编号,但不知道文件名,则可以使用 V$DATAFILE 来获取文件名:

SELECT name FROM v$datafile WHERE file#=&AFN;

如果文件号未显示在 Oracle8i 的 V$DATAFILE 中,且 &AFN 大于 DB_FILES 参数值,则该文件可能是临时文件。在这种情况下,可以使用以下查询找到文件名:

SELECT name FROM v$tempfile WHERE file#=(&AFN – &DB_FILES_value);

  • 文件中坏块的块编号。
    本文中称为“&BL”。
  • 包含受影响块的表空间编号和名称。
    本文中称为“&TSN”(表空间编号)和“&TABLESPACE_NAME”。
    如果您不知道这些信息,请使用以下查询找到它们:

SELECT ts# “TSN” FROM v$datafile WHERE file#=&AFN;
SELECT tablespace_name FROM dba_data_files WHERE file_id=&AFN;

  • 表空间中的坏块大小。
    本文中称为“&TS_BLOCK_SIZE”。

SELECT block_size FROM dba_tablespaces
WHERE tablespace_name =
(SELECT tablespace_name FROM dba_data_files WHERE file_id=&AFN);

对于 Oracle 7、8.0 和 8.1,数据库中所有表空间使用相同的块大小。
对于这些版本,使用命令”SHOW PARAMETER DB_BLOCK_SIZE” 返回的值作为 “ &TS_BLOCK_SIZE”

例如:对于 ORA-1578 错误:

ORA-01578: ORACLE data block corrupted (file # 7, block # 12698)
ORA-01110: data file 22: ‘<path>/<datafilename>.dbf’
那么:

&AFN      为 “22″     (从错误 ORA-1110 部分获得)
&RFN      为 “7″      (从错误 ORA-1578 的”file #”部分获得)
&BL       为 “12698″  (从错误 ORA-1578 的”block #”部分获得)
&FILENAME 为 ‘<path>/<datafilename>.dbf’
&TSN 及其他信息可以从上面提到的 SQL 语句获得

对于其他错误(ORA-600、ORA-1498 等),上述值应由 Oracle Support 提供给您,或从涵盖相关错误的文章中获取。

对于某些错误,如 ORA-1410“invalid ROWID(无效 ROWID)”、ORA-12899“value too large for column(列值过大)”等,未给出损坏的文件/块的详细信息。对于此类情况, Note:869305.1 可以帮助您定位损坏的行。

{go to content}

概述处理坏块的步骤

有多种原因可能导致坏块,包括:

    • 坏的 IO 硬件/固件
    • OS 问题
    • Oracle 问题
    • 对于执行过“UNRECOVERABLE”或“NOLOGGING”操作的数据库进行恢复
      (在这种情况下可能产生 ORA-1578 错误 – 如下方所示)

产生 Oracle 错误的时间点可能要比最初发生任何块损坏的时间点晚得多。

在遇到坏块时,我们通常无从了解根本原因,并且在大多数情况下,当下最迫切的需求是重新启动数据库并使其运行起来,正因如此,本文将介绍用于解决坏块问题的步骤,如下所列:

  1. 确定坏块问题的范围,并确定这些问题是持久性问题还是暂时性问题。

如果问题涉及范围很大,或错误不稳定,则关键在于先识别原因(检查硬件等)。这点很重要,因为如果是底层硬件出现错误,恢复系统便毫无意义。

 

  1. 更换或拆下任何有问题的或可疑的硬件。
  2. 确定哪些数据库对象受到影响。
  3. 选择最合适的数据库恢复/数据抢救选项。

对于上述所有步骤,最好应收集证据并详细记录所采取的措施。本文中的“证据>>”标签列出了应收集的信息,以帮助您识别问题的根本原因。

由于 NOLOGGING 或 UNRECOVERABLE 操作导致的坏块

如果对某个对象执行了 NOLOGGING(或 UNRECOVERABLE)操作,随后又恢复了包含该对象的数据文件,则受到 NOLOGGING 操作影响的数据块将被标记为“坏块”,当您访问该数据块时将显示 ORA-1578 错误。
从Oracle8i开始报错ORA-26040(“ORA-26040: Data block was loaded using the NOLOGGING option”),此时原因一目了然,而较早版本中则没有附件这条错误消息。如果坏块是由于对执行过 NOLOGGING 操作的数据文件进行恢复而产生的,则可以使用本文中从  Section 3 “Information to Record for Each Corruption” 开始之后介绍的内容,但请注意以下问题:

 

    1. 恢复操作无法找回受 NOLOGGING 操作影响的数据
    2. 块内的数据无法抢救
    3. 解决方法请参考Note:794505.1


(1) 确定坏块问题的范围

请参考Note 836658.1查找坏块的范围。使用 RMAN或者DBVERIFY 扫描受影响的文件(以及一切重要的文件)也是不错的办法,这样可以检查是否有其他坏块,从而确定问题的范围。有关使用 DBVERIFY 的详细信息,请参阅 Note:35512.1

每次发生坏块错误时,都应记下完整的错误消息,并查看该实例的告警日志和跟踪文件,以了解任何相关的错误。首先进行这些步骤非常重要,这可以评估该损坏是单个块,还是由于 UNRECOVERABLE 操作产生的错误,抑或是更严重的问题。

一旦确定了损坏的文件/块组合列表,即可使用以下步骤来帮助确定应采取何种措施。

证据:

  • 完整记录初始错误,以及发生错误的应用程序的详细信息。
  • 及时地保存从告警日志中首次 (FIRST) 记录到问题前数小时到当前时间点所提取的内容。
  • 保存告警日志中提到的任何跟踪文件。
  • 记录最近遇到的任何 OS 问题。
  • 记录是否正在使用任何特殊功能,例如:ASYNC IO、快速写入磁盘选项等。
  • 记录当前的备份位置(日期、类型等)
  • 记录数据库是否处于 ARCHIVELOG 模式,
    例如:在SQL*Plus(或 Server Manager)中运行“ARCHIVE LOG LIST”

(2) 更换或拆下可疑硬件

大多数坏块问题是由故障硬件导致的。
如果出现硬件错误或可疑组件,最好进行修复,或者在执行恢复操作之前,确保在单独的磁盘子系统上有足够的可用空间用于恢复。

您可以使用以下步骤移动数据文件:

    • 确保要迁移的文件已离线或数据库实例处于 MOUNT 状态(未打开)
    • 将该数据文件物理还原(或复制)到新位置
      例如:/newlocation/myfile.dbf
    • 将该文件的新位置告知 Oracle。
      例如:ALTER DATABASE RENAME FILE ‘/oldlocation/myfile.dbf’ TO ‘/newlocation/myfile.dbf’;
      (请注意,您不能对临时文件进行重命名,而应删除临时文件并在新位置重新创建)

重要信息:  如果存在多个错误(不是由于 NOLOGGING操作导致的)
或 受影响文件所在的 OS 层面出现错误
或 错误是暂时性的且游离不定,
那么,如果不解决底层问题或准备另外的磁盘空间,那么进行任何操作都是毫无意义的。
与硬件供应商联系,以全面检查系统,并联系 Oracle Support,告知所有错误详情。
请注意: 如果硬件检查失败,即表明存在硬件问题,但硬件检查成功通过却并不能证明没有硬件相关问题 — 硬件测试报告成功但确实存在底层错误,这种情况也是经常发生。

如果使用了任何特殊 IO 选项,例如 direct IO、async IO 或类似的选项,最好将其禁用,以消除这些选项成为潜在问题原因的可能性。

(3) 每次坏块需记录的信息

在决定如何恢复之前,最好先确定哪些对象受到了影响,因为坏块可能发生在那些容易被重新创建的对象中。
例如:对于只有 5 行数据的表中发生的坏块,删除并重新创建表可能要比执行恢复快得多。

对于每个坏块,请收集下表中的信息。
进行此操作的步骤如下所述。

针对每次坏块需记录的信息
初始错误 绝对文件号

&AFN

相关文件号 

&RFN

块编号 

&BL

表空间 段类型
所有者.名称
相关对象 恢复选项

下列说明将有助于您针对每个坏块填写此表。

  1.  “初始错误”最初报告的错误。例如:ORA-1578/ORA-1110、ORA-600 和所有参数等。
  2. “绝对文件号”, “相关文件号”和”块号”文件号和块号应该已在错误中显示,或由 Oracle Support 提供,或在指引您参考本文章的其他文章的步骤中提供。
    在 Oracle8/8i/9i/10g 中: 绝对文件号和相关文件号通常是一样的,但也可能不同(尤其是在数据库是由 Oracle7 迁移而来的情况下)。请务必获得正确的 &AFN 和 &RFN 编号,否则您可能最终抢救的是错误的对象!!
    ORA-1578 报告相关文件号,绝对文件号在伴随的 ORA-1110 错误中显示。对于 ORA-600 错误,您应该会被告知绝对文件号。
    下列查询将显示数据库中数据文件的绝对和相关文件号:

SELECT tablespace_name, file_id “AFN”, relative_fno “RFN” FROM dba_data_files;[Insert code here. Use 'Paste from Word' to retain layout.]

在 Oracle8i/9i/10g 中:
除了上述关于 Oracle8 的说明外,从 Oracle8i 开始将拥有临时文件。下列查询将显示数据库中临时文件的绝对和相关文件号:

SELECT tablespace_name, file_id+value “AFN”, relative_fno “RFN” FROM dba_temp_files, v$parameter WHERE name=’db_files’;

在 Oracle7 中: “绝对文件号”和“相关文件号”使用相同的文件号

  1. “段类型”, “所有者”, “名称”和”表空间”
    在给定坏块的绝对文件号“&AFN”和块编号“&B”的情况下,下列查询将显示对象的段类型、所有者和名称,数据库必须打开才能使用此查询:

SELECT * FROM dba_extents
WHERE file_id = &AFN
and &BL between block_id AND block_id + blocks – 1;

  1. 如果坏块位于临时文件中,则上述查询将不会返回任何数据。
    对于临时文件,“段类型”应为“TEMPORARY”。

    如果上述查询未返回行,也可能是因为坏块是本地管理表空间 (Locally Managed Tablespace, LMT) 中的段头。当坏块为 LMT 中的段头块时,上述查询将在 alert.log 中生成一个坏块消息,但查询不会失败。在这种情况下,请使用以下查询:

SELECT owner, segment_name, segment_type, partition_name
FROM dba_segments
WHERE header_file = &AFN
and header_block = &BL;

{go to content}


(4) Which Object is affected and 可能的恢复选项:

相关对象和能够使用的恢复选项取决于 SEGMENT_TYPE。对于各种最常见的段类型,其他查询和可能的恢复选项如下所列。

CACHE
CLUSTER
INDEX PARTITION
INDEX
LOBINDEX
LOBSEGMENT
ROLLBACK
TABLE PARTITION
TABLE
TEMPORARY

IOT
TYPE2 UNDO
Some other Segment Type
“no rows” from the query


CACHE

如果段类型为 CACHE,请再次检查您是否输入了正确的 SQL语句和参数。

解决方法:修复数据块采用块级恢复方法

{Continue}  {Back to Segment List}

CLUSTER

如果段类型为 CLUSTER,则应确定它包含哪些表。

例如:  SELECT owner, table_name fROM dba_tables WHERE owner=’&OWNER’ AND cluster_name=’&SEGMENT_NAME’;

解决方法:
修复数据块采用块级恢复方法

{Collect TABLE information}  {Back to Segment List}

 

INDEX PARTITION

如果段类型为 INDEX PARTITION,请记录名称和所有者,然后确定哪些分区受到影响:

SELECT partition_name
FROM dba_extents
WHERE file_id = &AFN AND &BL BETWEEN block_id AND block_id + blocks – 1

 解决方法:

修复数据块采用块级恢复方法

或者
使用下列语句可以重建索引分区:
ALTER INDEX xxx REBUILD PARTITION ppp;
(请注意下方“重建索引”中所述的 REBUILD 选项)

{Continue}  {Back to Segment List}

INDEX

确定索引位于哪个表中:

SELECT table_owner, table_name
FROM dba_indexes
WHERE owner=’&OWNER’ AND index_name=’&SEGMENT_NAME’;

CONSTRAINT_TYPE 的可能值包括:
-  P    索引支持主键约束。
-  U    索引支持唯一约束。
如果索引支持主键约束(类型“P”),则确认主键是否被任何外键约束引用:

SELECT owner, constraint_name, constraint_type, table_name
FROM dba_constraints
WHERE r_owner=’&TABLE_OWNER’ AND r_constraint_name=’&INDEX_NAME’;

  解决方法:
修复数据块采用块级恢复方法

或  重建索引(任何相关联的约束会随之禁用/启用)
(请注意下方”重建索引“中所述的 REBUILD 选项)。如果对象owner是sys用户,那么请联系oracle技术支持。

{Continue}  {Back to Segment List}

ROLLBACK

如果段类型为 ROLLBACK,请联系 Oracle Support,因为 ROLLBACK 段坏块需要特殊处理。

解决方法:
修复数据块采用块级恢复方法

{Continue}  {Back to Segment List}

TYPE2 UNDO

TYPE2 UNDO 是系统管理的 undo 段,它是 rollback 段的一种特殊形式。这些段的坏块需要特殊处理。

解决方法:
修复数据块采用块级恢复方法

{Continue}  {Back to Segment List}

TABLE PARTITION

如果段类型为 TABLE PARTITION,请记录名称和所有者,然后确定哪些分区受到影响:

SELECT partition_name
FROM dba_extents
WHERE file_id = &AFN
AND &BL BETWEEN block_id AND block_id + blocks – 1;

然后按照处理 TABLE 段的步骤继续下面的操作。

解决方法:

修复数据块采用块级恢复方法

或者
如果所有坏块均位于同一个分区,则此时可以采取的一个做法是用一个空表 EXCHANGE 坏块所在的分区,这可以让应用程序继续运行(无法访问坏块所在的分区中的数据),然后可以从之前的空表中提取任何未损坏的数据。
有关其他选项,请参见下面的 TABLE 选项。

{Continue}  {Back to Segment List}

TABLE

如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。
可能需要恢复数据库。

对于非字典 TABLE 或 TABLE PARTITION,确定表中存在哪些索引:

例如: SELECT owner, index_name, index_type
FROM dba_indexes
WHERE table_owner=’&OWNER’
AND table_name=’&SEGMENT_NAME’;

并确定表中是否存在任何主键:

例如:SELECT owner, constraint_name, constraint_type, table_name
FROM dba_constraints
WHERE owner=’&OWNER’
AND table_name=’&SEGMENT_NAME’
AND constraint_type=’P’;

如果存在主键,则确认它是否被任何外键约束引用:

例如:
SELECT owner, constraint_name, constraint_type, table_name
FROM dba_constraints
WHERE r_owner=’&OWNER’
AND r_constraint_name=’&CONSTRAINT_NAME’;

解决方法:
修复数据块采用块级恢复方法

或者

如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。

对于非字典表,可能的选项包括:
恢复
或  抢救表(或分区)中的数据
然后 重新创建表(或分区)
或  忽略坏块
(例如:使用 DBMS_REPAIR 标记需要跳过的问题块)

{Continue}  {Back to Segment List}

IOT(索引组织表)

IOT 表中的坏块应按照表或分区表中的处理方式来处理。
唯一的例外是如果 PK 损坏。
IOT 表的 PK 就是表本身,它不能被删除和重新创建。

解决方法:
修复数据块采用块级恢复方法  或者 参考下面的“从坏块表中提取坏块周围数据的方法” 来抽取数据。

或者

如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。

对于非字典表,可能的选项包括:
恢复
或  抢救表(或分区)中的数据
然后 重新创建表(或分区)
或  忽略坏块
(DBMS_REPAIR 不适用于 IOT)

{Continue}  {Back to Segment List}

LOBINDEX

确定 LOB 属于哪个表:

SELECT table_name, column_name
fROM dba_lobs
wHERE owner=’&OWNER’
AND index_name=’&SEGMENT_NAME’;

不可以重建 LOB 索引,因此您必须将该问题作为受影响的表中 LOB 列上的坏块来处理。
使用 ”TABLE“ 部分中的 SQL 语句获取包含损坏的 LOB 索引的表的索引和约束信息,然后返回此处。

解决方法

修复数据块采用块级恢复方法

或者

移动LOG 段

alter table &table_owner.&table_with_lob move LOB (&&lob_column) store as (tablespace &tablespace_name);

如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。
{Continue}  {Back to Segment List}

LOBSEGMENT

确定 LOB 属于哪个表:

例如:
SELECT table_name, column_name
FROM dba_lobs
WHERE owner=’&OWNER’
AND segment_name=’&SEGMENT_NAME’;

对于非字典表 …

使用 ”TABLE“ 部分中的 SQL 语句获取包含坏块的 LOB 数据的表的索引和约束信息,然后返回此处查找具体受影响的行的详细信息。

要查找引用损坏的 LOB 块的具体行可能比较困难,因为报告的错误中不会显示表中的哪一行数据包含损坏的 LOB 数据。

Typically one can refer to application logs or any SQL_TRACE or 10046 trace of a session hitting the error (if available) or see if having

event “1578 trace name errorstack level 3″

set in the session helps identify the current SQL/binds/row.

例如:
ALTER SYSTEM SET EVENTS ’1578 trace name errorstack level 3′;

然后等待应用程序触发该错误,并查找跟踪文件。

如果没有任何线索,您可以构建 PLSQL 块,逐行扫描问题表以提取 LOB 列数据,扫描将一直循环进行,直至发生错误。此方法可能需要一段时间,但它应该可以找到引用了损坏的 LOB 块的数据行的主键或 ROWID。

例如:
set serverout on
exec dbms_output.enable(100000);
declare
error_1578 exception;
pragma exception_init(error_1578,-1578);
n number;
cnt number:=0;
badcnt number:=0;
begin
for cursor_lob in
(select rowid r, &LOB_COLUMN_NAME L from &OWNER..&TABLE_NAME)
loop
begin
n:=dbms_lob.instr(cursor_lob.L,hextoraw(‘AA25889911′),1,999999) ;
exception
when error_1578 then
dbms_output.put_line(‘Got ORA-1578 reading LOB at ‘||cursor_lob.R);
badcnt:=badcnt+1;
end;
cnt:=cnt+1;
end loop;
dbms_output.put_line(‘Scanned ‘||cnt||’ rows – saw ‘||badcnt||’ errors’);
end;
/

another script more generic:

set serverout on
exec dbms_output.enable(100000);
declare
pag    number;
len    number;
c      varchar2(10);
charpp number := 8132/2;

begin
for r in (select rowid rid, dbms_lob.getlength (<your_clob_column>) len
from   <your_table_with_clcob_column>) loop
if r.len is not null then
for page in 0..r.len/charpp loop
begin
select dbms_lob.substr (<your_clob_column>, 1, 1+ (page * charpp))
into   c
from   <your_table_with_clcob_column>
where  rowid = r.rid;

exception
when others then
dbms_output.put_line (‘Error on rowid ‘ ||R.rid||’ page ‘||page);
dbms_output.put_line (sqlerrm);
end;
end loop;
end if;
end loop;
end;
/

 解决方法:


可能需要恢复数据库,如果所有者为“SYS”,则联系 Oracle Support 并上传所有详细信息。

对于非字典表,可能的选项包括:

恢复

或者用empty_clob/empty_blob更新lob列,避免在出现ORA-1578;这样可以清理表里面的lob列:

SQL> set concat off
SQL> update &table_owner.&table_with_lob
set &lob_column = empty_blob()
where rowid in (‘list the identified rowids from the table from the plsql above’);

将损坏的lob设置为empty lob后,之前的数据块还会放回这个lob的freelist。这些空间以后可能会被重用,
当这些数据块再次被使用时,会出现ORA-1578 错误,因此在empty lob后,再将lob 段移动到新的段:

alter table &table_owner.&table_with_lob move LOB (&&lob_column) store as (tablespace &tablespace_name);

或  抢救表(及其 LOB 列)中的数据
然后 重新创建表
或  忽略坏块
(不可以在 LOB 段上使用 DBMS_REPAIR)

 

{Continue}  {Back to Segment List}

TEMPORARY

如果段类型为 TEMPORARY,则坏块不会影响永久对象。检查发生问题的表空间是否正在被用作 TEMPORARY 表空间:

SELECT count(*) FROM dba_users WHERE temporary_tablespace=’&TABLESPACE_NAME’;

解决方法:

参考Note 1332088.1

通常情况下,不需要进行任何还原,但如果磁盘可能有问题,且表空间包含有用数据,则最好对数据库中受影响的文件进行恢复。

 

{Continue}  {Back to Segment List}

其他一些段类型

如果返回的段类型未包含在上述类型中,则请联系 Oracle Support 并提供迄今为止收集的所有信息,以获得相关建议。

 

{Continue}  {Back to Segment List}

“无返回行”

如果没有包含坏块的 extent,则首先再次检查查询中使用的参数。如果您确定文件号和块编号是正确的,且不属于 DBA_EXTENTS 中的某个对象,则执行以下操作:

  • 再次检查相关文件是否为临时文件。
    请注意,临时文件的文件号取决于数据库初始化参数 DB_FILES,因此对该参数的任何更改都会改变错误中报告的绝对文件号。
  • DBA_EXTENTS 不包含本地管理表空间中用于本地空间管理的块。
  • 如果您在数据库运行查询语句的时间点与出错的时间点不相同,那么问题对象可能已经被删除,因此针对 DBA_EXTENTS 的查询可能不会显示任何行。
  • 如果您正在调查的错误由 DBVERIFY 报告,则 DBV 将检查所有块,而不管它们是否属于某个对象。因此,坏块可能存在于数据文件中,但却未被任何对象使用。

选项:

未使用的 Oracle 块(出现在dba_free_space的块)上的错误可以忽略,因为如果需要使用该块,oracle会在对这个块做DML操作时格式化。
注意,简单的extent的分配不会格式化这个块,而且DML操作必须去使用或者修改这个块
如果你想手工格式化这个块,你可以参考: How to Format Corrupted Block Not Part of Any Segment Document 336133.1

如果您怀疑该块可能是空间管理块,则可以使用 DBMS_SPACE_ADMIN 包来帮助您进行检查:

exec DBMS_SPACE_ADMIN.TABLESPACE_VERIFY(‘&TABLESPACE_NAME’);

以上命令会将不一致写入跟踪文件,但如果遇到致命的坏块,它将报告如下错误:

ORA-03216: Tablespace/Segment Verification cannot proceed

 

{Continue}  {Back to Segment List}

{go to content}

证据

对于每个坏块,如果需要尝试并确定实际坏块原因,则收集如下物理证据也是一个比较好的方法:

  1. 坏块及位于其任意一侧的块的操作系统 HEX 转储。

    在 UNIX 上:

dd if=&FILENAME bs=&TS_BLOCK_SIZE skip=&BL-1 count=3 of=BL.dd
^^^^^^^^      ^^^^^^^^^^^^^^         ^^^
例如:对于 BL=1224:

dd if=ts11.dbf bs=4k skip=1223 count=3 of=1223_1225.dd
在 VMS 上:

DUMP/BLOCKS=(start:XXXX,end:YYYY)/out=dump.out &FILENAME
其中 XXXX=操作系统块编号(512 字节块中)
要计算此值,用报告的块编号乘以“&TS_BLOCK_SIZE/512”。

  1. 处于 ARCHIVELOG 模式时,复制出错时间前后的归档日志文件的安全副本,最好包括报告错误前数小时的日志文件。并且,保存问题数据文件在出错前的所有副本,因为之前的数据文件映像以及 redo 记录有助于找出错误原因。
    (DBV 通常可用于检查问题是否存在于文件的备份副本中)。理想的情况是获得没有报告坏块的数据文件备份映像,以及从该时间点开始到首次报告坏块时间之后不久的时段内的所有 redo 记录。
  2. 获得问题块的 Oracle 转储:

ALTER SYSTEM DUMP DATAFILE ‘&FILENAME’ BLOCK &BL;

(DUMP将生成到 USER_DUMP_DEST 下的跟踪文件)。

 

{Continue}  {Back to Segment List}

{go to content}

(5) 选择恢复选项

现在,最佳的恢复选项取决于受影响的对象。前面第 (3) 部分中的说明应该已经重点介绍了针对每个受影响对象的主要可用选项。选择的实际恢复方法可能包含以下一种或多种混合方法:

是否需要进行任何恢复操作?

表空间中,或位于不再属于任何数据库对象的块中,则无需进行任何操作,尽管将问题表空间重定位到其他存储设备中可能较为明智。

请参阅警告

可以使用完全恢复吗?

要选用完全恢复,必须满足如下条件:

  • 数据库处于 ARCHIVELOG 模式

(“ARCHIVE LOG LIST”命令显示 Archivelog 模式)

  • 拥有受影响文件的完好备份。请注意,在某些情况下,坏块可能已经存在,但在很长一段时间内未被发现。如果最近的数据文件备份仍包含坏块,那么只要您拥有所 有必需的归档日志,就可以尝试使用更早的备份。
    (通常可以使用 DBV START= / END= 选项来检查位于某个备份文件的恢复副本中的特定块是否损坏)
  • 从备份时间开始到当前时间点的所有归档日志均可用
  • 当前的在线日志均可用且完好无缺
  • 错误不是由运行 NOLOGGING 操作之后执行的恢复所导致的

如果满足上述条件,完全恢复通常是首选方法

*但请注意*

  1. 如果事务回滚已发现坏块位于对象上,而非 rollback 段本身,则 undo 操作可能已被放弃。在这种情况下,可能需要在恢复完成后重建索引/检查数据完整性。
  2. 如果要恢复的文件包含自上次备份以来执行的 NOLOGGING 操作的数据,在使用了数据文件或数据库恢复的情况下,这些块将被标记为“坏块”。在某些情况下,这会使情况更加糟糕。

如果执行数据库恢复后坏块仍然存在,则表示所有备份都包含坏块,底层错误仍存在,或问题通过 redo 重现。在这些情况下,需要选择其他一些恢复选项。

请参阅 “(4A) 完全恢复” ,以了解完全恢复步骤。

{go to content}

如果不需要从对象本身提取任何数据,能否删除或重新创建该对象?

您可以删除对象或从脚本/最近导出的副本重新创建对象。一旦删除一个对象后,该对象中的块将被标记为“空闲”,并且该块在被分配到新对象时将被重新格式化。明智的做法是,对表进行重命名,而不是删除,除非您完全确定不再需要其中的数据。

对于表分区,只需要删除受影响的分区。

例如: ALTER TABLE … DROP PARTITION …

如果坏块影响到分区段头,或者包含分区头的文件处于离线状态,则 DROP PARTITION 可能会失败。在这种情况下,首先将其更换为具有相同定义的表,之后仍然可以删除该分区。

例如: ALTER TABLE .. EXCHANGE PARTITION .. WITH TABLE ..;

最常见的可重建对象为索引。始终在处理表中的索引问题之前处理表坏块。
有关详细信息,请参阅”(4B) 重建索引” 。

对于任何段,如果您拥有坏块的绝对文件号和块号,则可使用以下快速提取对象 DDL 的方法:

set long 64000
select dbms_metadata.get_ddl(segment_type, segment_name, owner)
FROM dba_extents
WHERE file_id=&AFN
AND &BL BETWEEN block_id AND block_id + blocks -1;

{go to content}

是否需要在重新创建对象之前抢救数据?

如果问题位于定期更新的关键应用表上,则可能需要尽可能多地抢救表中数据,然后重新创建该表。

有关详细信息,请参阅”(5C) 抢救表中数据” 。

{go to content}

当前忽略坏块是否可取?

在某些情况下,最直接的选项可能就是忽略坏块,并阻止应用程序对它进行访问。

有关详细信息,请参阅 “(5D) 忽略坏块“。

{go to content}

最后的选项

下列选项是否可行?

将数据库或表空间恢复到较早的时间点(通过时间点恢复)

或还原出现坏块前的冷备份

或使用现有导出文件

有关详细信息,请参阅”(5E) 最后的选项“。

{go to content}

 (5A) 完全恢复

如果数据库处于 ARCHIVELOG 模式下,且您拥有受影响文件的完好备份,则恢复通常为首选方法。
这不保证可以解决问题,但的确可以有效的解决大部分坏块问题。如果恢复再次引发问题,则返回到以上选项列表并选择其他方法。

如果使用的是 Oracle9i(或更高版本),则可以使用 RMAN BLOCKRECOVER 命令执行块级恢复。
如果使用的是较早版本的 Oracle,则可以执行数据文件恢复(数据库其他部分可以继续运行),或数据库恢复(需要关闭数据库)。

如果使用的是 Oracle 11g(或更高版本),则可以使用“Data Recovery Advisor(数据恢复指导)”.

块级恢复

自 Oracle9i 版本起,RMAN 允许恢复单个块,同时数据库的其他部分(包括数据文件中的其他块)仍可以进行正常访问。请注意,块级恢复只能将块完全恢复到当前时间点。

例如:

实际情况是,文件 6 的块 30 上发生 ORA-1578 错误,可能是由于介质问题导致的坏块,且您拥有该文件的完好冷备份映像,并已还原到“…/RESTORE/filename.dbf”。
假设所有归档日志均存在(位于默认位置),则可以通过 RMAN 使用以下命令序列执行块级恢复:

rman nocatalog
connect target
catalog datafilecopy ‘…/RESTORE/filename.dbf’;
run {blockrecover datafile 6 block 30;}

此操作将使用注册的数据文件备份映像和任何需要的归档日志来执行块恢复,仅将有问题的块恢复到当前时间点。

有关 RMAN BLOCKRECOVER 命令和限制的所有详细信息,请参阅文档 Note 144911.1

{go to content}

数据文件恢复

数据文件恢复包括下列步骤。如果有多个文件,则针对每个文件重复执行这些步骤,或参阅下面的“数据库恢复”。当数据库处于 OPEN 或 MOUNTED 状态时,均可使用这些步骤。

使受影响的数据文件离线

例如: ALTER DATABASE DATAFILE ‘name_of_file’ OFFLINE;

将文件复制到安全位置(以防备份损坏)

将文件的最新备份还原到完好的磁盘上

使用 DBVERIFY 检查还原的文件是否有坏块
有关使用 DBVERIFY 的详细信息,请参阅 Note:35512.1

假设还原的文件完好,则将数据文件重命名并保存到新位置(如果不是原来的位置)

例如: ALTER DATABASE RENAME FILE ‘old_name’ TO ‘new_name’;

恢复数据文件

例如: RECOVER DATAFILE ‘name_of_file’;

使数据文件上线

例如: ALTER DATABASE DATAFILE ‘name_of_file’ ONLINE;

{Continue}

{go to content}

数据库恢复

数据库恢复通常包含以下步骤:

关闭数据库(使用选项 immediate 或 abort)

将待恢复的所有文件的当前副本复制到安全位置

将备份文件还原到完好的磁盘上
请勿还原控制文件或在线 REDO 日志文件

使用 DBVERIFY 检查还原的文件。有关使用 DBVERIFY 的详细信息,请参阅 Note:35512.1

启动数据库到MOUNT状态(startup mount)

对任何需要重新定位的数据文件进行重命名

例如: ALTER DATABASE RENAME FILE ‘old_name’ TO ‘new_name’;

确保所有必需的文件在线

例如: ALTER DATABASE DATAFILE ‘name_of_file’ ONLINE;

恢复数据库

例如: RECOVER DATABASE

打开数据库

例如: ALTER DATABASE OPEN;

{go to content}

完全恢复后

一旦执行了完全恢复,最好在允许使用之前先检查数据库:

针对每个问题对象运行:

“ANALYZE <table_name> VALIDATE STRUCTURE CASCADE”

检查表/索引是否存在不匹配。

如果有任何 undo 操作曾被放弃,此命令可能会显示不匹配,此时需要重建索引。

在应用程序级别检查表中数据的逻辑完整性。

{go to content}

(5B) 重建索引

损坏对象为用户索引时,如果底层表没有损坏,则可以删除并重建该索引。
如果底层表也已经损坏,则应在重建任何索引之前先解决该表的坏块。

如果收集的信息表示索引有从属外键约束,则需要执行以下操作:

  • 对于每个外键

ALTER TABLE <table> DISABLE CONSTRAINT <pk_constraint>;

  • 使用以下命令重建主键

ALTER TABLE <table> DISABLE CONSTRAINT <pk_constraint>;
DROP INDEX <index_name>;
CREATE INDEX <index_name> .. with appropriate storage clause
ALTER TABLE <table> ENABLE CONSTRAINT <pk_constraint>;

  • 启用外键约束

ALTER TABLE <child_table> ENABLE CONSTRAINT <fk_constraint>;

对于索引分区,可以执行以下命令:

ALTER INDEX … REBUILD PARTITION …;

注意:

  1. 不要使用“ALTER INDEX ..  REBUILD”命令重建损坏的非分区索引,这一点非常重要,因为此操作通常会尝试从包含坏块的现有索引段中构建新索引。

“ALTER INDEX … REBUILD ONLINE” and “ALTER INDEX … REBUILD PARTITION …”
不会从旧索引段中构建新索引,因此可以使用。

  1. 如果新索引包含的列为现有索引的子集,则 Create INDEX 可以使用现有索引中的数据。因此,如果您有两个损坏的索引,应在重建之前将两个都删除。
  2. 重建索引时,请确保使用正确的存储选项。

{go to content}

(5C) 抢救表中数据

如果损坏的对象为 TABLE 或 CLUSTER 或 LOBSEGMENT,则您必须明白,坏块内的数据已经丢失。
部分数据可能可以从块的 HEX 转储中,或从索引涵盖的列中抢救回来。

重要信息:
由于可能需要从索引中抢救坏块中的数据,因此最好不要删除任何现有索引,直至所有需要的数据提取完成。

从包含坏块的表中提取数据有多种方法。选择最恰当的方法,详细信息如下所述。这些方法的目的是从可访问的表块中提取尽可能多的数据。通常,将损坏的表重命名是一个比较好的方法,这样就可以使用正确的名称创建新对象。

例如: RENAME <emp> TO <emp_corrupt>;

从坏块表中提取坏块周围数据的方法

  1. 从 Oracle 7.2 开始(包括 Oracle 8.0、8.1 和 9i),可以跳过表中的坏块。
    这是到目前为止最简单的提取表数据的方法,此方法在以下文档中做了讨论:

    Extracting data using DBMS_REPAIR.SKIP_CORRUPT_BLOCKS or Event 10231  Note:33405.1
    如果坏块位于 IOT overflow 段,则应使用相同的方法,不同的是使用 Event 10233 和全索引扫描或者在10.2.0.4/10.2.0.5 使用event:43810; 在11g之后,使用参数:_index_scan_check_skip_corrupt=TRUE。请参考文档:Note:1527738.1 中的“SKIP ORA-600 in IOT”部分。

    请注意,此方法只适用于块的“包装”已被标记为“坏块”的情况。例如:如果块报告 ORA-1578 错误。
    如果问题为 ORA-600 或其他非ORA-1578 错误,则通常可以使用 DBMS_REPAIR 将表中坏块标记为“软坏块”。这样在您访问该数据块时,系统将显示 ORA-1578 错误,从而可以使用 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS。

    注意:被“FIX_CORRUPT_BLOCKS”程序标记为“坏块”的块在任何还原/恢复操作之后还将被标记为“坏块”.

    有关使用 DBMS_REPAIR 进行此操作的全部详细信息,请参阅相关文档,但概括起来说,步骤如下:

- 使用 DBMS_REPAIR.ADMIN_TABLES 创建管理表
- 使用 DBMS_REPAIR.CHECK_OBJECT 找到问题块
- 在损坏问题块之前将其中所有完好的数据导出。
- 使用 DBMS_REPAIR.FIX_CORRUPT_BLOCKS 将找到的问题块标记为“坏块”,然后它们就会显示 ORA-1578
- 如果需要,使用 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS 跳过表中的坏块。

  1. 从 Oracle 7.1 开始,可以使用 ROWID 范围扫描。
    此功能的语法较为复杂,但可以使用 ROWID 提示选择坏块周围的数据。
    由于 Oracle7 和 Oracle8 中的 ROWID 格式有所不同,故有两篇文章分别介绍此功能:

    Using ROWID Range Scans to extract data in Oracle8 and higher Note:61685.1
    Using ROWID Range Scans to extract data in Oracle7 Note:34371.1

  2. 如果存在主键,则可以通过此索引选择表数据。
    也可以通过任何其他索引选择一些数据。
    此方法较慢,花费时间较长,通常只有 Oracle 7.0 版本才使用。此方法在 Note:34371.1 中进行了介绍(此外,还介绍了 ROWID 范围扫描)。
  3. 有多种抢救程序/PLSQL 脚本可用于抢救表中的数据。与上述方法相比,这些方法在设置和使用方面需要花费更长的时间,但常常能够处理除 ORA-1578 之外的各类坏块。
    由于这些方法通常需要由技术支持人员给予大量的亲身指导,因此客户可能看不到关于这些方法的部分文章。

    要使用以下程序,需要使用 Pro*C,且需要了解如何构建 Pro*C 可执行文件:

    SALVAGE.PC for Oracle8.1 Note:97357.1

    要使用以下程序,需要手动交互:

    SALVAGE.SQL for Oracle7/8 Note:2064553.4
    SALVAGE.SQL for Oracle7/8 Note:28308.1
    The following is only possible in Oracle8i and 9i. The aim is to mark the block as corrupt and then use the SKIP_CORRUPT table attribute to extract the table data:

    Use DBMS_REPAIR to mark the block corrupt Note:68013.1
    For corruption in a LONG column: Recreating a Table with a corruption in a LONG Note:876493.1

{go to content}

从包含损坏的 LOBSEGMENT 块的表中提取数据的方法

在 LOB 段上不可以使用 DBMS_REPAIR。

如果坏块 LOB 块未被表中的任何行引用,则应该可以使用 CREATE TABLE as SELECT (CTAS) 来按选择创建表,或按原样导出/删除/导入该表。

如果坏块 LOB 块被某个行引用,则应该可以使用不包括问题行的 WHERE 谓词进行选择或导出。

警告:
可以将问题行的 LOB 列值更新为 NULL,从而使 SELECT 操作不再返回ORA-1578 错误 *但是* 坏块将等待被重新使用,随着对行中的 LOB 列进行 INSERT 或 UPDATE 操作,当有问题的块被重新使用时,最后还是会报ORA-1578错误,那时的情况比已知行出现坏块更糟糕。
因此,只有您打算立刻重新创建表,才应该将 LOB 列设为 NULL。

从坏块本身提取数据

由于坏块本身已经“损坏”,则从该块中提取的任何数据都应被视为可疑数据。从坏块本身获取数据行的主要方法包括:

  • 对于 TABLE 的块,Oracle Support 可以使用一款尝试解释块内容的工具。
    “Convert HEX or BLOCKDUMP to Readable form” Note:47419.1
  • 使用表中现有索引,利用落在坏块内的ROWID 来提取索引所涵盖的列数据,上文提到的 ROWID 范围扫描文章在接近结束时对此内容有所介绍:
    对于 Oracle8/8i,请参阅 Note:61685.1
    对于 Oracle7,请参阅 Note:34371.1
  • 在 redo 流上可以使用 LogMiner 来查找向问题块加载数据的初始插入/更新操作。此处的主要因素是数据实际被放入问题块的时间。
    例如,行 2 可能在昨天已插入,而行 1 可能在 5 年前已插入。

{go to content}

(5D) 忽略坏块

出错时可以忽略坏块并接受报告的错误,或在应用程序级别阻止对出问题的块行进行访问。

例如:如果问题块/行位于子表中,则可以在应用程序级别阻止对父表中对应行的访问,从而子行就永不会被访问。(但要注意级联类约束)

这样做可能不利于批量访问数据的报告和其他任务,因此,为了阻止块在被访问时报错,前面 4C 中所述的 DBMS_REPAIR 选项也不失为一个可取的方法。使用这种方法标记并跳过坏块提供了一种短期的解决方案,从而在计划停机时可以尝试进行完全数据抢救和/或恢复,或留出更多时 间在第二个(克隆)数据库上尝试其他恢复选项。但请注意,使用 DBMS_REPAIR.FIX_CORRUPT_BLOCKS 标记块坏块将导致标记的块在恢复后还是“坏块”。

忽略坏块对于快速老化且即将被清除的数据而言是比较好的选择(例如,在按日期分区的表中,较老的分区将在某时间点被删除)。

忽略 LOB 段上的坏块

在应用程序级别,可以忽略损坏的 LOB 列,直到可以重新构建该表。

确保不出现上述“警告”中的情形的一种方法是,确保应用程序只能通过表上的包含WHERE 谓词的视图来访分表中的数据。
例如:假设表 MYTAB(a number primary key,b clob)有一行或多行指向损坏的 LOB 数据。

ALTER TABLE MYTAB ADD ( BAD VARCHAR2(1) );
CREATE VIEW MYVIEW AS SELECT a,b FROM MYTAB WHERE BAD is null;

对任何问题行设置 BAD=’Y’

如果只通过 MYVIEW 访问 MYTAB,该行将永不可见,因此也无法更新,从而实现了坏块条目隔离,直到问题解决。

很明显,此示例更多的是一个设计时解决方案,但某些应用程序可能已有类似机制,且可能只通过某个视图(或通过 RLS 策略)访问数据,从而提供某些选项来隐藏问题行。

{go to content}

针对忽略坏块的警告

虽然可以忽略坏块,但需要注意的是,坏块在运行 DBVERIFY、RMAN 备份时仍然会以警告/错误等形式出现。

请务必仔细记录您将在这些工具中看到的任何坏块,尤其是您期望在使用 RMAN 时跳过的任何块(例如,设置了 MAX_CORRUPT),并确保在清除坏块后移除任何对错误的“接受”选项。

例如:假设坏块已处理为忽略坏块,并在应用程序级别跳过问题行。
RMAN 可能被配置为在备份时接受坏块。
然后在稍后的表重组期间重新创建表。
如果 RMAN 配置未及时更新以反映目前已无任何错误,则 RMAN 可能会忽略稍后出现的某些其他坏块。

此外,还有重要的一点需要注意,忽略 table 段中的坏块可能导致查询返回不一致的结果。
例如:设置了 SKIP_CORRUPT 的表可能出现不同的结果,具体取决于是使用了了索引扫描还是表访问。
其他报告可能只是报错。

请注意,如果忽略坏块但使用 DBMS_REPAIR.FIX_CORRUPT_BLOCKS 标记,系统会向坏块中写入 redo 信息,这可能会限制后续的恢复选项。

{go to content}

(5E) 最后的选项

如果你有 standby 环境(物理或逻辑),请首先对其进行检查。
无论问题发生在何种类型的块上,均可使用一种可能的选项,即将数据库或问题表空间恢复到出现坏块之前的某个时间点。此选项的困难之处在于,并不总能知道问题首次出现的时间。

DBVERIFY 通常可用于检查还原的文件是否存在坏块。
有关使用 DBVERIFY 的详细信息,请参阅Note:35512.1 。尤其是,START= / END= DBV 选项可用于在还原的备份映像上快速进行首次测试,以检查问题块本身是否出错。

 

本部分列出了一些可用于进行恢复操作的最终选项。
如果您看到这里,则必定发生了以下一种或多种情况:

  • 您丢失了非常重要的数据文件(或数据文件出现坏块),而没有问题文件的正常备份(无坏块)
  • 既不处于 ARCHIVELOG 模式,也没有自文件创建以来的全部归档日志
  • 完全恢复后仍重复出现问题

最后的机会:

请注意,如果您丢失了数据文件的所有副本,但仍具有自文件创建以来的全部归档日志,则仍有可能恢复该文件。

例如:
ALTER DATABASE CREATE DATAFILE ‘….’ [as '...'] ;
RECOVER DATAFILE ‘….’
ALTER DATABASE DATAFILE ‘….’ ONLINE;

如果您遇到这种情况,请在继续下面的操作之前先尝试使用这些步骤来恢复数据文件。

如果您到达这一步,就说明没有其他办法可以将文件恢复到当前时间点。此时最好关闭实例,并对当前数据库进行备份,以便在选用的措施失败后仍然能够回退到当前时间点。(例如:如果发现备份坏块)。

可用的一些选项概述如下:

恢复到早期的冷备份
- 例如:如果处于 NOARCHIVELOG 模式

从冷备份建立克隆数据库,并提取(导出)问题表,或传输问题表空间。

使用基于时间点的恢复将数据库恢复到一致的时间点

  • 需要完好备份和任何所需的归档日志
  • 必须还原所有文件且将整个数据库前滚到恰当的时间点。
  • 可以在克隆数据库中执行基于时间点的恢复,然后将问题表空间传输到问题数据库,或将问题表利用导出/导入工具从克隆数据库导入到问题数据库。

表空间基于时间点的恢复
- 可以仅对受影响的表空间执行基于时间点的恢复。许多文档均对表空间基于时间点的恢复做了介绍,如 Note:223543.1.

从逻辑导出/副本重新创建数据库
- 需要具有完好的数据库逻辑备份
- 注意:要使用此选项,必须重新创建数据库。
- 与其他选项一样,可以在克隆数据库中进行重新创建,只为获得问题表的完好映像。

如果已具有完好备份,使用 DB_BLOCK_CHECKING=TRUE 进行前滚将有助于找到首次出错的时间点。在调查恢复选项时,通常不需要关闭问题数据库。

例如:可以只将系统表空间和问题表空间数据文件还原到完全不同的位置和/或机器,作为不同的实例,以便于调查可以前滚到多久以前的时间点等。
自 Oracle9i 起,您还可以使用“试验恢复”选项来让自己摆脱一边研究选项一边必须不断还原备份的情形。

转载:处理 Oracle 块损坏 (Doc ID 1526911.1)