Oracle 写丢失保护/影子表空间(Lost Write Protection with Shadow Tablespace)

写丢失是Oracle数据库与独立I/O子系统交互时一种错误场景。假如Oracle发出的写磁盘命令,I/O子系统也返回成功写磁盘的消息(但数据此时可能依然在I/O系统缓存中),如果在I/O系统实际写盘之前Oracle再次读取该数据,则I/O系统可能会返回旧版本的数据(写操作丢失了)。Oracle引入了写丢失保护机制,通过在读数据时校验数据块的SCN,以检测是否出现写丢失。

目录

  • 一、写丢失简介
    • [1.1 影子表空间](#1.1 影子表空间)
  • 二、配置写丢失保护
    • [2.1 创建影子表空间](#2.1 创建影子表空间)
    • [2.2 数据库级别打开写丢失保护](#2.2 数据库级别打开写丢失保护)
    • [2.3 为指定对象开写丢失保护](#2.3 为指定对象开写丢失保护)
    • [2.4 关闭写丢失保护](#2.4 关闭写丢失保护)

一、写丢失简介

写丢失是由I/O系统缓存机制造成的,I/O系统可能在并没有实际写盘的情况下给Oracle返回了写盘成功的信息。如果此时Oracle再次读取该数据块,那么读到的依然是旧版本的数据。

从Oracle的角度来看,虽然上一次的写盘已经成功执行,但再次读取的却是旧版本数据。如果在旧版数据上进行DML,那么就会造成数据损坏,更糟的情况是:如果依据读取的旧版数据更新了其他数据,那么将导致数据损坏扩散至全库。

1.1 影子表空间

Oracle引入了影子表空间来追踪数据块的更新SCN。影子表空间不保存普通数据,而是被记录数据块最后一次写磁盘的SCN(System Change Number 系统变更号)。对于开启写丢失保护的表空间/文件,每次读取数据块时,都会将从磁盘读取到数据块的SCN和影子表空间记录的SCN对比,如果发现磁盘读取数据块的SCN小于影子表空间中记录的SCN,则发生了写丢失。

例如:某个数据块初始SCN为1,读入内存后被更新为2,数据块写磁盘的同时Oracle将SCN为2记录到影子表空间。随后I/O子系统给Oracle返回写盘成功(但实际仍在I/O缓存中)。此时Oracle再次读取该数据块,但I/O系统返回的依然是SCN为1的数据,而影子表空间的记录的SCN为2,Oracle意识到发生了写丢失并抛出错误。

二、配置写丢失保护

写丢失保护由普通表空间和影子表空间共同完成,你可以在表空间或数据文件级别开启写丢失保护。由于开启此特性有一定的性能开销(每次读取都要校验SCN),你可以根据需要仅为最重要的数据开启写丢失保护。

2.1 创建影子表空间

影子表空间必须是大文件表空间(Bigfile Tablespace),使用create bigfile tablespace和lost write protection子句创建影子表空间:

sql 复制代码
create bigfile tablespace shadowtbs lost write protection;

影子表空间创建完成后,可以通过dba_tablespaces视图来查看(contents列是LOST WRITE PROTECTION):

sql 复制代码
select tablespace_name, status, contents
from dba_tablespaces
where tablespace_name='SHADOWTBS';

2.2 数据库级别打开写丢失保护

创建完影子表空间后,需要使用alter database语句先在数据库级别打开写丢失保护特性:

sql 复制代码
alter database enable lost write protection;

注:多租户环境下,CDB级别开启写丢失保护,PDB并不会继承,需要显式使用alter pluggable database语句在PDB级别开启。

2.3 为指定对象开写丢失保护

打开数据库的写丢失保护特性后,就可以为表空间或数据文件开启写丢失保护了。如果保护对象是表空间则其包含的所有文件都会加入写丢失保护(包括后续增加的数据文件)。

示例:为表空间users开启写丢失保护:

sql 复制代码
alter tablespace users enable lost write protection;

开启后可以根据dba_tablespaces来确实表空间是否开启写丢失保护,lost_write_protect显示enabled说明users表空间已打开写丢失保护:

sql 复制代码
select tablespace_name, status, lost_write_protect
from dba_tablespaces
where tablespace_name='USERS';

由于是在表空间级别开启,后续添加的数据文件都会自动加入写丢失保护,新添加一个数据文件users02.dbf,通过dba_data_files可以看到写丢失保护自动打开了:

sql 复制代码
alter tablespace users add datafile '/u01/app/oracle/oradata/PROD/users02.dbf' size 20m;
select file_name, tablespace_name, lost_write_protect
from dba_data_files
where tablespace_name='USERS';

示例:通过file_id为指定数据文件开启写丢失保护:

sql 复制代码
alter database datafile 5 enable lost write protection;

开启后可以通过dba_data_files.lost_write_protect确认(lost_write_protect => enabled):

sql 复制代码
select file_id, tablespace_name, lost_write_protect
from dba_data_files
where tablespace_name='NEW_TBS';

2.4 关闭写丢失保护

使用alter tablespace ... remove lost wirte protection关闭表空间的写丢失保护:

sql 复制代码
alter tablespace users remove lost write protection;

使用alter database datafile ... suspend lost write protection关闭数据文件的写丢失保护:

sql 复制代码
alter database datafile 5 suspend lost write protection;
相关推荐
minhuan4 分钟前
大模型应用:从交易行为到实时反欺诈:向量数据库驱动的智能风控实践.33
数据库·向量数据库·大模型应用·chromadb数据库
Guheyunyi6 分钟前
视频安全监测系统的三大核心突破
大数据·运维·服务器·人工智能·安全·音视频
晴天¥12 分钟前
Oracle中的安全管理(用户、权限、角色)
数据库·安全·oracle
Xの哲學16 分钟前
Linux UPnP技术深度解析: 从设计哲学到实现细节
linux·服务器·网络·算法·边缘计算
柏木乃一20 分钟前
进程(6)进程切换,Linux中的进程组织,Linux进程调度算法
linux·服务器·c++·算法·架构·操作系统
Jelly-小丑鱼21 分钟前
Linux搭建SQLserver数据库和Orical数据库
linux·运维·数据库·sqlserver·oracal·docker容器数据库
JIngJaneIL22 分钟前
基于springboot + vue健康管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·后端
秋饼23 分钟前
【三大锁王争霸赛:Java锁、数据库锁、分布式锁谁是卷王?】
java·数据库·分布式
Run_Teenage25 分钟前
Linux:进程等待
linux·运维·服务器
电商API&Tina26 分钟前
【电商API接口】关于电商数据采集相关行业
java·python·oracle·django·sqlite·json·php