
1. 外部数据篡改、侵入的情况确实可能存在(后面我举例说明),通过OS级别的数据块替换,可以改写数据(更不要说类似BBED的工具);
2. 大部分自研的国产数据库,还做不到精确校验和防范这类情况,我测试过几种,大家可以针对性的测试一下。由开源演进而来的国产数据库,具备一定的写丢失安全检测能力。
3. Oracle在 12.2 版本开始实现了严谨的写丢失检测机制。
***
Corrupt block seq: 37288 blocknum=1.
Bad header found during deleting archived log
Data in bad block - seq:810559520. bno:170473264. time:707406346
beg:21280 cks:21061
calculated check value: 9226
Reread of seq=37288, blocknum=1, file=/ARCH/arch_1_37288_632509987.dbf, found same corrupt data
Reread of seq=37288, blocknum=1, file=/ARCH/arch_1_37288_632509987.dbf, found same corrupt data
Reread of seq=37288, blocknum=1, file=/ARCH/arch_1_37288_632509987.dbf, found same corrupt data
Reread of seq=37288, blocknum=1, file=/ARCH/arch_1_37288_632509987.dbf, found same corrupt data
Reread of seq=37288, blocknum=1, file=/ARCH/arch_1_37288_632509987.dbf, found same corrupt data
***
strings arch_1_37288_632509987.dbf > log.txt
Dump file ADMIN/bdump/erp_p007_19216.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options
ORACLE_HOME = DBMS/erp/erpdb/10g
Linux
2.6.9-34.ELhugemem
i686
Instance name: erp
Redo thread mounted by this instance: 1
Oracle process number: 22
Unix process pid: 19216, image: oracle@eygle.com (P007)
KCRP: blocks claimed = 61, eliminated = 0
----- Recovery Hash Table Statistics ---------
Hash table buckets = 32768
Longest hash chain = 1
Average hash chain = 61/61 = 1.0
Max compares per lookup = 0
Avg compares per lookup = 0/61 = 0.0
----------------------------------------------
----- Recovery Hash Table Statistics ---------
Hash table buckets = 32768
Longest hash chain = 1
Average hash chain = 61/61 = 1.0
Max compares per lookup = 1
Avg compares per lookup = 1426/1426 = 1.0
----------------------------------------------
\GPAYMENTdxn
AP_CHECKS
PaymentsN
a'VND
Userxn
AP_INVOICE_PAYMENTS
105273
5406105305-20101020-003
3001CASH CLEARING
CREATED
在Oracle 11g中,引入了DB_LOST_WRITE_PROTECT特性,通过这个参数可以启用或禁用丢失的写入检测。当I/O子系统确认块写入完成,而实际上写入没有或错误的发生在持久存储中,就意味着发生了数据块写入丢失,这个特性用于检测这种情况。
l当主数据库上的参数设置为TYPICAL时,实例会在重做日志中记录读写(Read Write)表空间的Buffer Cache读取信息,这对于检测丢失的写入是必需的。
l当主数据库上的参数设置为FULL时,实例日志将为只读(Read-Only)表空间以及读写(Read-Write)表空间产生额外记录。
lTYPICAL模式的性能开销约为5到10%,对于FULL模式可能更高。
SQL> select banner from v$version;BANNER---------------------------------------------------------------Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 - ProductionSQL> alter system set db_lost_write_protect='TYPICAL';System altered.
SQL> select open_mode from v$database;OPEN_MODE--------------------READ ONLY WITH APPLYSQL> alter system set db_lost_write_protect='TYPICAL';System altered.
SQL> create tablespace lostwrite datafile size 10M;Tablespace created.SQL> create user enmo identified by enmo default tablespace lostwrite;User created.SQL> grant connect,resource,dba to enmo;Grant succeeded.SQL> connect enmo/enmoSQL> create table enmotech (id number);Table created.SQL> insert into enmotech values(200);1 row created.SQL> commit;Commit complete.SQL> alter system flush buffer_cache;System altered.SQL> alter system switch logfile;System altered.
[oracle@DEVDB datafile]$ cp o1_mf_lostwrit_g47tb4vg_.dbf o1_mf_lostwrit_g47tb4vg_.dbf.old
SQL> update enmotech set id=888;1 row updated.SQL> commit;Commit complete.SQL> select * from enmotech;ID----------888SQL> alter system flush buffer_cache;System altered.
SQL> select * from enmo.enmotech;ID----------888
[oracle@DEVDB datafile]$ cp o1_mf_lostwrit_g47tb4vg_.dbf.old o1_mf_lostwrit_g47tb4vg_.dbf
SQL> select * from enmotech;ID----------200
2019-01-20T11:21:40.836426+08:00create tablespace lostwrite datafile size 10M2019-01-20T11:21:41.725876+08:00Control autobackup written to DISK devicehandle '/fast_recovery_area/DB18C/autobackup/2019_01_20/o1_mf_s_998047301_g47tb5mb_.bkp'Completed: create tablespace lostwrite datafile size 10M2019-01-20T11:23:30.535149+08:00ALTER SYSTEM: Flushing buffer cache inst=0 container=0 global2019-01-20T11:23:44.006236+08:00Thread 1 advanced to log sequence 1722 (LGWR switch)Current log# 1 seq# 1722 mem# 0: DB18C/onlinelog/o1_mf_1_f9ovsb94_.log2019-01-20T11:23:44.087462+08:00ARC1 (PID:23353): Archived Log entry 153 added for T-1.S-1721 ID 0x3926be67 LAD:12019-01-20T11:23:44.125533+08:00TT03 (PID:7880): SRL selected for T-1.S-1722 for LAD:22019-01-20T11:25:39.365092+08:00ALTER SYSTEM: Flushing buffer cache inst=0 container=0 global
2019-01-20T11:26:03.408260+08:00Errors in file db18c_s/DB18C_S/trace/DB18C_S_mz00_28990.trc:ORA-00312: online log 2 thread 1: '/DB18C/onlinelog/o1_mf_2_f9ovsbj1_.log'ORA-27037: unable to obtain file statusLinux-x86_64 Error: 2: No such file or directoryAdditional information: 7Standby redo application has detected that the primary database lost a disk write.No redo at or after SCN 0x0000000015734233 can be used for recovery.BLOCK THAT LOST WRITE 133, FILE 2, TABLESPACE# 7The block read during the normal successful database operation had SCN 359874679 (0x0000000015734077) seq 1 (0x01)ERROR: ORA-00752 detected lost write on primarySlave exiting with ORA-752 exception2019-01-20T11:26:03.555719+08:00Recovery Slave PR02 previously exited with exception 7522019-01-20T11:26:04.501889+08:00Background Media Recovery process shutdown (DB18C_S)
2019-01-20T11:26:04.442236+08:00PR00 (PID:28727): MRP0: Background Media Recovery terminated with error 4482019-01-20T11:26:04.442855+08:00Errors in file db18c_s/DB18C_S/trace/DB18C_S_pr00_28727.trc:ORA-00448: normal completion of background processPR00 (PID:28727): Managed Standby Recovery not using Real Time ApplyRecovery interrupted!
2019-01-22T13:22:27.415907+08:00Errors in file db18c/DB18C/trace/DB18C_ckpt_20835.trc:ORA-63999: data file suffered media failureORA-01122: database file 2 failed verification checkORA-01110: data file 2: '/DB18C/datafile/o1_mf_lostwrit_g47tb4vg_.dbf'ORA-01208: data file is an old version - not accessing current version
SQL> recover datafile 2;ORA-00279: change 359874547 generated at01/20/2019 11:21:40 needed for thread 1ORA-00289: suggestion : /DB18C/archivelog/2019_01_20/o1_mf_1_1721_g47tg02b_.arcORA-00280: change 359874547 for thread 1 is in sequence #1721ORA-00283: recovery session canceled due to errorsORA-00752: recovery detected a lost write of a data blockORA-10567: Redo is inconsistent with data block (file# 2, block# 133, file offset is 1089536 bytes)ORA-10564: tablespace LOSTWRITEORA-01110: data file 2: '/DB18C/datafile/o1_mf_lostwrit_g47tb4vg_.dbf'ORA-10561: block type 'TRANSACTION MANAGED DATA BLOCK', data object# 186211
SQL> alter system set db_lost_write_protect=none;System altered.RMAN> recover datafile 2;Starting recover at2019-01-22 13:47:50using target database control file instead of recovery catalogallocated channel: ORA_DISK_1channel ORA_DISK_1: SID=151 device type=DISKstarting media recoveryarchived log for thread 1 with sequence 1722 is already on disk as file /archivelog/2019_01_22/o1_mf_1_1722_g4fb3ghj_.arcarchived log for thread 1 with sequence 1723 is already on disk as file /archivelog/2019_01_22/o1_mf_1_1723_g4fb442h_.arcarchived log for thread 1 with sequence 1724 is already on disk as file /archivelog/2019_01_22/o1_mf_1_1724_g4fbdlcq_.arcarchived log for thread 1 with sequence 1725 is already on disk as file /archivelog/2019_01_22/o1_mf_1_1725_g4fbg000_.arcarchived log for thread 1 with sequence 1726 is already on disk as file /archivelog/2019_01_22/o1_mf_1_1726_g4fbh4wv_.arcarchived log for thread 1 with sequence 1727 is already on disk as file /archivelog/2019_01_22/o1_mf_1_1727_g4fbj7hc_.arcarchived log for thread 1 with sequence 1728 is already on disk as file /archivelog/2019_01_22/o1_mf_1_1728_g4fcmbvx_.arcarchived log file name=/archivelog/2019_01_22/o1_mf_1_1722_g4fb3ghj_.arc thread=1 sequence=1722archived log file name=/archivelog/2019_01_22/o1_mf_1_1723_g4fb442h_.arc thread=1 sequence=1723archived log file name=/archivelog/2019_01_22/o1_mf_1_1724_g4fbdlcq_.arc thread=1 sequence=1724archived log file name=/archivelog/2019_01_22/o1_mf_1_1725_g4fbg000_.arc thread=1 sequence=1725media recovery complete, elapsed time: 00:00:05Finished recover at2019-01-22 13:47:57RMAN> alter database datafile 2 online;Statement processed
SQL> create bigfile tablespace shadow_tbs datafile '/DB18C/datafile/shadow_tbs.dbf' size 200M lost write protection;Tablespace created.SQL> select CONTENTS from DBA_TABLESPACES where TABLESPACE_NAME='SHADOW_TBS';CONTENTS---------------------LOST WRITE PROTECTION
SQL> alter database enable lost write protection;Database altered.SQL> alter tablespace lostwrite enable lost write protection;Tablespace altered.SQL> select * from database_properties where property_name ='NEW_LOST_WRITE';PROPERTY_NAME PROPERTY_V DESCRIPTION-------------------- ---------- ------------------------------NEW_LOST_WRITE TRUE new lost write protectionSQL> select LOST_WRITE_PROTECT from DBA_TABLESPACES where TABLESPACE_NAME='LOSTWRITE';LOST_WR-------ENABLED
SQL> create index idxid on enmotech(id);Index created.SQL> select DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) BLOCK#, DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) RFILE#,a.* from enmo.enmotech a;BLOCK# RFILE# ID---------- ---------- ----------132 2 999133 2 888133 2 888134 2 666
[oracle@DEVDB datafile]$ dd if=o1_mf_lostwrit_g47tb4vg_.dbf bs=8192 count=1 skip=132 of=bakblk132.dmp1+0 records in1+0 records out8192 bytes (8.2 kB) copied, 0.000160311 s, 51.1 MB/s
SQL> insert into enmotech values(777);1 row created.SQL> commit;Commit complete.SQL> select DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) BLOCK#, DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) RFILE#,a.* from enmo.enmotech a;BLOCK# RFILE# ID---------- ---------- ----------132 2 999132 2 777133 2 888133 2 888134 2 666
[oracle@DEVDB datafile]$ dd of=o1_mf_lostwrit_g47tb4vg_.dbf bs=8192 count=1 seek=132 if=bakblk132.dmp conv=notrunc1+0 records in1+0 records out8192 bytes (8.2 kB) copied, 0.000212014 s, 38.6 MB/s

SQL> connect enmo/enmoConnected.SQL> select * from enmotech;select * from enmotech*ERROR at line 1:ORA-65478: shadow lost write protection - found lost write
2019-02-10T22:25:14.776576+08:00ERROR - I/O type:buffered I/O found lost write in block with file#:2 rdba:0x800084, Expected SCN:0x0000000015bd951a SCN in block:0x0000000015bd84e6, approx current SCN:0x0000000015bdab52, RAC instance:1 pdb:0
SQL> alter database disable lost write protection;Database altered.SQL> select * from enmotech;ID----------999888888666
SQL> select * from enmotech where id=777;ID----------777Execution Plan----------------------------------------------------------Plan hash value: 3880444692--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 4 | 1 (0)| 00:00:01 ||* 1 | INDEX RANGE SCAN| IDXID | 1 | 4 | 1 (0)| 00:00:01 |--------------------------------------------------------------------------





