Oracle RAC业务bug导致部分数据丢失处理
REMAP_SCHEMA 将一个方案中的对象加载到另一个方案。
REMAP_TABLE 表名重新映射到另一个表,例如 REMAP_TABLE=EMP.EMPNO:REMAPPKG.EMPNO。
REMAP_TABLESPACE 将表空间对象重新映射到另一个表空间。
REUSE_DATAFILES 如果表空间已存在, 则将其初始化 (N)。
REMAP_SCHEMA参数
众所周知:IMP工具的FROMUSER和TOUSER参数可以实现将一个用户的的数据迁移到另外一个用户。
impdp数据泵使用REMAP_SCHEMA参数来实现不同用户之间的数据迁移;
语法:
REMAP_SCHEMA=source_schema:target_schema
impdp orcldev/oracle DIRECTORY=backup_path DUMPFILE=oracldev.dmp REMAP_SCHEMA=orcldev:orcltwo
与REMAP_SCHEMA类似的参数选项,如REMAP_TABLESPACE将源表空间的所有对象导入目标表空间。
REMAP_TABLE参数
将源表数据映射到不同的目标表中
impdp orcldev/oracle DIRECTORY=backup_path dumpfile=oracldev.dmp remap_table=TAB_TEST:TEST_TB
数据导入到TEST_TB表中,但是该表的索引等信息并没有相应的创建,需要手工初始化。
REMAP_DATAFILE参数
语法:REMAP_DATAFILE=source_datafile:target_datafile
Oracle_Online:
Remapping datafiles is useful when you move databases between platforms that have different file naming conventions. The source_datafile and target_datafile names should be exactly as you want them to appear in the SQL statements where they are referenced. Oracle recommends that you enclose datafile names in quotation marks to eliminate ambiguity on platforms for which a colon is a valid file specification character.
4. 查找丢失数据,导入正式库表T_GL_BALANCE中
SQL> alter table tmp_t_gl_balance_inibak drop column FYEARPERIOD; --删除自动生成的唯一字段
SQL> insert into t_gl_balance select * from tmp_t_gl_balance_inibak where faccountbookid=151508; --插入查询结果时少字段
SQL> alter table tmp_t_gl_balance_inibak add FYEARPERIOD NUMBER; --将删除字段加回来
SQL> insert into t_gl_balance select * from tmp_t_gl_balance_inibak where faccountbookid=151508; --插入查询结果时报错
ORA-11523: Message 11523 not found; product=RDBMS; facility=ORA google没有找到对应报错
直接在数据库服务器上操作:
sqlplus user/passwd@scan-ip/实例名
SQL> insert into t_gl_balance select * from tmp_t_gl_balance_inibak where faccountbookid=151508;
ORA-54013: INSERT operation disallowed on virtual columns 报错已经很明显了,通过指定列名来进行插入
SQL> insert into t_gl_balance(FACCOUNTBOOKID,FYEAR,FPERIOD,FACCOUNTID,FDETAILID,FCURRENCYID,FBEGINBALANCEFOR,FBEGINBALANCE,FDEBITFOR,FDEBIT,FCREDITFOR,FCREDIT,FYTDDEBITFOR,FYTDDEBIT,FYTDCREDITFOR,FYTDCREDIT,FENDBALANCEFOR,FENDBALANCE,FADJUSTPERIOD) select FACCOUNTBOOKID,FYEAR,FPERIOD,FACCOUNTID,FDETAILID,FCURRENCYID,FBEGINBALANCEFOR,FBEGINBALANCE,FDEBITFOR,FDEBIT,FCREDITFOR,FCREDIT,FYTDDEBITFOR,FYTDDEBIT,FYTDCREDITFOR,FYTDCREDIT,FENDBALANCEFOR,FENDBALANCE,FADJUSTPERIOD from tmp_t_gl_balance_inibak where faccountbookid=151508;
插入成功,将其他丢失数据批量恢复
5. 问题原因及问题出现的操作和时间节点
原因:业务系统BUG,反过账操作会将前一期数据清除
SQL>select to_char(FDATETIME,‘YYYY-MM-DD HH24:mi:ss‘),FDESCRIPTION,FCLIENTIP from t_bas_operatelog where fdescription like ‘%过账%‘ and to_char(FDATETIME,‘YYYY-MM-DD‘) in (‘2019-10-25‘,‘2019-10-26‘);
SQL>select to_char(FDATETIME,‘YYYY-MM-DD HH24:mi:ss‘),FDESCRIPTION,FCLIENTIP from t_bas_operatelogbk where fdescription like ‘%过账%‘ and to_char(FDATETIME,‘YYYY-MM-DD‘) in (‘2019-10-25‘,‘2019-10-26‘);
通过日志追溯到了时间及具体操作等,接下来就是让业务系统厂家打补丁了。
Oracle RAC业务bug导致部分数据丢失处理
标签:sch 通过 定义数据 taf 成功 mic close 加载 path
小编还为您整理了以下内容,可能对您也有帮助:
oracle数据库一个表里面的数据丢失了一部分,但是在v$sql里面没有查到操
日志挖掘,分析归档日志和当前日志文件;
如何解决Oracle Rac数据不同步问题
现在有这样的环境:
一台web Server,一个是纯JAVA APP 程序
数据库两台做成RAC的形式. web Server与APP 程序都通过oci(rac)的方式连接数据库.
出了这样的怪问题,webServer更新或是插图入一条数据,后面紧跟着的在APP中就查询不到,等到用工具查询就没有问题.
初步怀疑
1. RAC方式下面的数据库两个instance的同步没做好?
查询相关资料发现在与MAX_COMMIT_PROPAGATION_DELAY有关.
最大提交传播时延(MAX_COMMIT_PROPAGATION_DELAY,简称MCPD),在ORACLE RAC(或OPS)环境中才使用,表示在RAC系统中,一个instance系统提交产生的最新系统改变码(SCN),能够以多快的速度反应到另一个instance中.
举例说明,RAC系统,有A,B两个实例(instance),A、B本地系统改变码为SCN1,A更新数据DATA1提交, LGWR操作完成后,A本地系统改变码为SCN2,经过不大于MAX_COMMIT_PROPAGATION_DELAY时间后,B系统本地改变码才变为SCN2.
Global Cache ServICes 将刷新RAC中的SCN.不管SCN是否及时刷新,后续的数据查询都不会因此产生数据库错误.但,在此时间内,有可能查询结果不是最新数据,产生读一致性(read consistency)问题.
RAC环境中的所有实例,此参数值必须相同.
ORACLE8i后,建议常用的两个值是0和700(默认),其他数值皆不建议.其实,这两个数值就代表了RAC环境中,两种SCN 产生机制:
Lamport Scheme和 Broadcast on Commit scheme.
设置为默认值700,表示采用Lamport Scheme,SCN改变不会完全同步,同步将在 7秒钟内完成,而不是总等待7秒钟后才完成.如果系统比较空闲,同步可能在0.5秒(甚至更短时间)内完成;不管系统多繁忙,同步时间也不可能超过7秒.不难理解,采用此模式,整个RAC系统的运行效率较高.
设置为0,表示采用Broadcast on Commit scheme,SCN改变完全同步.每当commit时(即LGWR 写redo log时):
- LGWR发送消息更新全局SCN(global SCN),
- LGWR 发送消息给每个活动的实例更新其本地SCN(LOCal SCN).
有资料说,只要MCPD < 700,系统将采用Broadcast on Commit scheme.
Lamport Scheme能够适应绝大部分应用的要求,只有个别实时性特别高的业务,才需要Broadcast on Commit scheme.通过分析,不难理解,Broadcast on Commit scheme将需要更多的系统资源.
oracle rac中一个节点坏了怎么重装与恢复(目前数据库在另一节点中正常运行)?谢谢!
给你推荐一个专门的ORACLE恢复软件,你试试怎么样
FROMBYTE Reconstructor for Oracle是一款用于恢复ORACLE数据库文件的软件产品,主要功能为重组ORACLE数据库碎片并导出完整的文件。
一、适用的灾难情况:
(1)ORACLE数据库文件被误删除 .
(2)存储重新分区、格式化导致ORACLE数据库文件丢失。
(3)存储突然断电、文件系统故障、fsck导致ORACLE数据库文件丢失。
(4)ASM存储故障导致ORACLE数据库文件丢失。
二、支持的文件系统特性:
(1)支持的文件系统类型:NTFS/EXT3/EXT4/REISERFS/REISER4/XFS/HTFS/UFS1/UFS2/JFS1/JFS2/VXFS/ASM.
(2)支持的文件系统平台:Little Endian/Big Endian.
(3)支持的文件系统块大小:512 Bytes/1 KB/2 KB/4 KB/8 KB/16 KB/32 KB.
三、支持的数据库特性:
(1)支持的数据库版本:ORACLE 8i/ORACLE 9 i/ORACLE 10g/ORACLE 11g.
(2)支持的数据库表空间模式:Smallfile Tablespace/Bigfile Tablespace.
(3)支持的数据库文件块大小:512 Bytes/1 KB/2 KB/4 KB/8 KB/16 KB/32 KB 及 自定义块大小。
四、其他特性:
(1)支持虚拟磁盘文件扫描及恢复。
(2)支持保存当前的扫描信息或加载已保存的扫描信息。
(3)支持创建自定义磁盘扫描区域或ASM磁盘组。
(4)支持千万级文件碎片扫描及多种不同的缓冲区大小。
(5)支持从数据库文件 ID/Size/Integrity/Version/Block Size多方面进行过滤搜索(针对数据库文件)。
(6)支持从数据库文件碎片 File ID/Block ID/Block Count/Block Size多方面进行过滤搜索(针对数据库文件碎片)。
(7)支持生成数据库文件可恢复性的技术报告。追问做广告呀,哈哈!不管怎样还是感谢一下吧!
怎么修复数据库 修复数据库坏块方法
修复数据库坏块
dbv
你也可以用dbv工具看一下你现在其他的数据文件有没有还有坏块的
dbv file='yourfilename'
恢复方法:
当Oracle数据库出现坏块时,Oracle会在警告日志文件(alert_SID.log)中记录坏块的信息:
ORA-01578: ORACLE data block corrupted (file # 7, block # )
ORA-01110: data file : '/oracle1/oradata/V920/oradata/V816/users01.dbf'
其中,<AFN>代表坏块所在数据文件的绝对文件号,代表坏块是数据文件上的第几个数据块
出现这种情况时,应该首先检查是否是硬件及操作系统上的故障导致Oracle数据库出现坏块。在排除了数据库以外的原因后,再对发生坏块的数据库对象进行处理。
1.确定发生坏块的数据库对象
SELECT tablespace_name,
segment_type,
owner,
segment_name
FROM dba_extents
WHERE file_id =
AND between block_id AND block_id+blocks-1;
2.决定修复方法
如果发生坏块的对象是一个索引,那么可以直接把索引DROP掉后,再根据表里的记录进行重建;
如果发生坏块的表的记录可以根据其它表的记录生成的话,那么可以直接把这个表DROP掉后重建;
如果有数据库的备份,则恢复数据库的方法来进行修复;
如果表里的记录没有其它办法恢复,那么坏块上的记录就丢失了,只能把表中其它数据坏上的记录取出来,然后对这个表进行重建。
3.用Oracle提供的DBMS_REPAIR包标记出坏块
exec DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('','');
4.使用Create table as select命令将表中其它块上的记录保存到另一张表上
create table corrupt_table_bak
as
select * from corrupt_table;
5.用DROP TABLE命令删除有坏块的表
drop table corrupt_table;
6.用alter table rename命令恢复原来的表
alter table corrupt_table_bak
rename to corrupt_table;
7.如果表上存在索引,则要重建表上的索引
PART2
2014.7.22研究恢复数据库坏块:
Oracle调用标准C的系统函数,对数据块进行读写操作,因此,坏块是有可能由以下几种原因产生:
硬件的I/O错误
操作系统的I/O错误或缓冲问题
内存或paging问题
磁盘修复工具
一个数据文件的一部分正在被覆盖
Oracle试图访问一个未被格式化的系统块失败
数据文件部分溢出
Oracle或者操作系统的bug
遇到“ORA-01578:ORACLE data block corrupted”错误
处理方法:1.rman的recover命令可以在数据库保持open状态下只恢复受损的数据块
2.如果没有备份,万不得已之下也可以采用DBMS_REPAIR包的存储过程将受损坏块隔离,同时尽可能地挽救部分数据。
rman backup命令也是检查坏数据块的好工具 一旦读取ORA-19566 即可有问题
此时可用backup validate tablespace user观察详细的信息,可查看到坏块数与跟踪文件
grep‘corrupt’/u01/app/oracle/diag/rdbms/br/br/trace/**.trc
恢复数据块:rman》recover datafile 5 block 203;
批量恢复受损的数据块:recover corruption list;
数据块坏块一号坏块,需要做:
run{
sql 'alter database datafile 5 offline';
restore datafile 5;
recover datafile 5;
sql'alter database datafile 5 online'
}
使用exp/imp恢复
在这种情况下肯定会造成数据的丢失,在这种情况下应采取将数据导出然后重建表再进行导入的方法,来尽量恢复损坏数据块中的数据,但是在有坏块的情况下是不允许导出的,如下命令:Exp test/test file=t.dmp tables=t;
导出命令在执行中会报ORA-01578错误,在这错误提示中会提示那个文件号的文件以及这个文件中的哪个块被损坏,如:ORA—01578:ORACLE 数据块损坏(文件号 4,块号 35)
针对以上的提示首先查询那些对象被损坏:
Select tablespace_name,segment_type,owner,segment_name From dba_extents Where file_id=4 and 35 between block_id and block_id+blocks-1;
如果被损坏的块是索引,通常可以通过索引重建来解决,如果损坏的是数据(segment_type为table),那么通过设置如下内部事件使得Exp操作跳过坏块。
Alter session set events=’10231 trace name context forever,level 10’;
然后重新执行导出命令,导出相关的表,然后执行Drop Table命令删除相关表,之后重建表最后导入数据。
使用DBMS_REPAIR恢复
用DBMS_REPAIR当然也会丢失数据。这里不做详细的介绍,有兴趣的可以查看oracle的在线文
3、使用dbms_repair包进行坏块处理
1)首先建立repair_table,用于存放dbms_repair.check_object检测出来的坏块信息
SQL> declare
2begin
3dbms_repair.admin_tables
4(table_name => 'REPAIR_TABLE',--表名
5table_type => dbms_repair.repair_table,
6action => dbms_repair.create_action,
7tablespace => 'USERS');--用于指定该表存放的表空间
8end;
9/
PL/SQL 过程已成功完成。
SQL> col owner format a10
SQL> col object_name format a20
SQL> col object_type format a20
SQL> select owner, object_name, object_type
2from dba_objects
3where object_name like '%REPAIR_TABLE';
OWNEROBJECT_NAMEOBJECT_TYPE
---------- -------------------- --------------------
SYSREPAIR_TABLETABLE
SYSDBA_REPAIR_TABLEVIEW
Oracle自动创建了一个DBA_REPAIR_TABLE视图。
2)使用dbms_repair.check_object进行坏块检测
SQL> set serveroutput on size 100000;
SQL> declare
2rpr_count int;
3begin
4rpr_count := 0;
5dbms_repair.check_object(
6schema_name => 'SYS',--指定对象模式,也就是对象的所有者
7object_name => 'TEST',--指定对象名,也就是表名
8repair_table_name => 'REPAIR_TABLE',
9corrupt_count => rpr_count);
10dbms_output.put_line('repair block count: '
11||to_char(rpr_count));
12end;
13/
repair block count: 4
PL/SQL 过程已成功完成。
SQL> select object_name, block_id, corrupt_type, marked_corrupt,
2corrupt_description, repair_description
3from repair_table;
OBJECT_NAMEBLOCK_ID CORRUPT_TYPE MARKED_COR
-------------------- ---------- ------------ ----------
CORRUPT_DESCRIPTION
-------------------------------------------------------------------------------
REPAIR_DESCRIPTION
-------------------------------------------------------------------------------
TEST196148 TRUE
mark block software corrupt
TEST206148 TRUE
mark block software corrupt
TEST236148 TRUE
mark block software corrupt
TEST316148 TRUE
mark block software corrupt
通过运行dbms_repair.check_object,将坏块信息存放到了repair_table表中,其中有个字段marked_corrupt,用于标识该块是否被标识为坏块,当被标识为true时,即该块被标识为坏块。其中这一步跟oracle文档中的描述有点进入,根据oracle文档,当执行完dbms_repair.check_object时,并不会进行坏块标识,也就是marked_corrupt列的值应该为false,而只有当执行dbms_repair.fix_corrupt_blocks过程后才会进行坏块标识。
3)使用dbms_repair.fix_corrupt_blocks进行坏块标识
SQL> declare
2fix_block_count int;
3begin
4fix_block_count := 0;
5dbms_repair.fix_corrupt_blocks (
6schema_name => 'SYS',
7object_name => 'TEST',
8object_type => dbms_repair.table_object,
9repair_table_name => 'REPAIR_TABLE',
10fix_count => fix_block_count);
11dbms_output.put_line('fix blocks count: ' ||
12to_char(fix_block_count));
13end;
14/
fix blocks count: 0
PL/SQL 过程已成功完成。
我们可以见到到fix blocks count=0,即在上一步进行check_object时已经进行了坏块标识了,这一步其实可以省略。(不过没有测试过!)