当对数据进行修改时,Oracle数据库会将旧的数据存储到UNDO表空间(回滚表空间)。回滚表空间让用户可以rollback到修改前的数据,提供了读一致性,并支持闪回查询过去的数据。Undo也用来在Transaction出问题的时候恢复数据,例如用户在执行事务的时候断开会话,没有进行rollback或者commit。或者实例出问题需要shutdown abort的时候,Oracle数据库会恢复数据到用户更改之前的状态。

回滚信息保留到以下条件发生:

  • rollback
  • commit
  • DDL(因为DDL会先Commit)
  • 用户不正常的断开会话(自动rollback到用户更改之前的数据)
  • 用户使用exit正常断开会话(自动commit)

Undo信息的存储

回滚数据保留的数量和保留的时间依赖于数据库的操作量以及初始化参数的设置。



进行数据操作的时候,数据值变化时,旧值就会被复制到UNDO表空间的UNDO段。Undo段是Oracle数据库自动创建用来支持Transaction的,和所有的段一样,Undo段也是由区组成,区由数据块组成。Undo段自动的增长与收缩,不需要认为干预。

Transaction填充undo段中的区,当transaction结束后,空间将会被回收。如果一个区被写满了,Transaction会从段中下一个区获得空间写入数据。当所有的区都被写满了,Transaction会回到段的第一个区开始重写或者再为段申请分配新的区。

Undo段自动创建,Owner是SYS用户。因为Undo是循环使用的,所以一个Undo段至少两个区。

Undo信息保存在Undo表空间,Undo表空间只能存储Undo段。DBCA创建数据库的时候,会自动创建一个small file的UNDO表空间,虽然可以创建Big file的Undo表空间,但如果在高并发的OLTP环境,大量并发的事务会造成对Undo文件头的争抢,Small File可以避免这个问题。

Undo表空间也是永久表空间,它的Extent Management采用的本地管理Locally Managed(相对于数据字典),Auto Extent Allocation(相对于Uniform)。

通过cdb_tablespaces查看每个容器的undo表空间名。

SQL> SELECT tablespace_name,extent_management,allocation_type, con_id
2 FROM cdb_tablespaces
3 WHERE tablespace_name like 'UNDO%'; TABLESPACE_NAME EXTENT_MAN ALLOCATIO CON_ID
------------------------------ ---------- --------- ----------
UNDOTBS1 LOCAL SYSTEM 1
UNDOTBS1 LOCAL SYSTEM 3

对比Undo与Redo数据

Undo用来撤销改变,并保证读一致性与闪回操作。Redo用来重现一个改变。Undo数据也写入到Redo日志中。

随着commit, redo数据被写入到redo日志文件中,redo日志文件存储在磁盘上,redo日志文件是多个副本同时存在磁盘上。Redo用来保证数据的一致性。

对比Shared与Local Undo模式

  • Shared Undo: 只在CDB$ROOT设置一个Undo表空间,所有的PDB公用。
  • Local Undo: 每个PDB有自己的Undo表空间。如果创建PLUGGABLE PDB的时候需要用到HOT CLONE或者NEAR-ZERO DOWN TIME PDB RELOCATION,必须使用LOCAL UNDO表空间。
启用共享UNDO表空间
SQL> STARTUP UPGRADE;
SQL> ALTER DATABASE LOCAL UNDO OFF; 启用本地UNDO表空间
SQL> STARTUP UPGRADE;
SQL> ALTER DATABASE LOCAL UNDO ON;

通过DATABASE_PROPERTIES试图可以查看LOCAL_UNDO_ENABLED的值, FALSE=SHARED UNDO TABLESPACE, TRUE=LOCAL UNDO TABLESPACE。

SQL> select property_name, property_value from database_properties
2 where property_name = 'LOCAL_UNDO_ENABLED'; PROPERTY_NAME PROPERTY_VALUE
-------------------- --------------------
LOCAL_UNDO_ENABLED FALSE

配置Undo

undo信息的三种状态

  • Active 没有提交的undo信息。这些信息永远不会覆写。
  • Unexpired 已经提交的undo信息,对于事务来说不再需要,但仍在retention interval内进行保留。如果没有Retention Guarantee,在UNDO表空间没有空间可用时的时候会被覆写。
  • Expired 已经提交并以超出retention interval的undo信息,会被active的undo信息覆写。

系统初始化参数UNDO_RETENTION(单位:秒)设置了在COMMIT之后的多少秒内保留Undo数据。

开启了AUTO-EXTENDING的UNDO表空间,这个值是UNDO信息的最短保留时间,也是最长的闪回操作时间。因为开启了AUTO-EXTENDING的UNDO表空间可能会自动重写已经提交但还没有过期的Undo信息,他可能会降低闪回操作能够回退的时间点。

为了避免没有过期的undo信息被重写从而影响闪回,可以设置保证回滚信息的保留期限Guarantee Undo Retention。

RETENTION GUARANTEE是表空间的属性,需要使用ALTER TABLESPACE <tbs name> RETENTION GUARANTEE | NOGUARANTEE 来设置。

启用RETENTION GUARANTEE

SQL> ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;
Tablespace altered.

禁用RETENTION GUARANTEE

SQL> ALTER TABLESPACE undotbs1 RETENTION NOGUARANTEE;
Tablespace altered.

RETENTION GUARANTEE只能设置在UNDO表空间,如果应用到其他表空间,命令执行会报错。

SQL> ALTER TABLESPACE users RETENTION GUARANTEE;
ALTER TABLESPACE users RETENTION GUARANTEE
*
ERROR at line 1:
ORA-30044: 'Retention' can only specified for undo tablespace

临时Undo



临时表也有undo信息,临时表的更改很频繁,将undo存在临时表中可以提升性能,主要是因为临时表空间中的更改不进行redo log的写入。

临时Undo的好处

  • 减少Undo表空间的使用量。
  • 减少到redo log的写入。
  • 使Oracle Active Data Guard的物理备用服务器可以在临时表空间进行DML(服务器上的TEMP_UNDO_ENABLED默认开启)。

启用临时UNDO

初始化参数TEMP_UNDO_ENABLED可以启用或者禁用临时UNDO。

可以在会话和系统级别定义这个参数。如果在会话级别启用,则只会在当前会话启用临时Undo,其他会话不受影响。如果在系统级别启用,所有当前会话和新会话都使用临时Undo。

SQL> ALTER SESSION SET temp_undo_enabled = True;
Session altered. SQL> ALTER SYSTEM SET temp_undo_enabled = False;
System altered.

监控临时Undo

V$TEMPUNDOSTAT包含了临时UNDO的统计信息,每十分钟进行一次统计。

Begin_Time: 统计开始时间

Txncount: 统计的十分钟内的Transaction数量。

MaxConcurrency: 最大的并发事务数。

Undoblkcnt: Temporary Undo使用的数据块数。

USCNT: 创建的Temp Undo段数量。

NoSPEERRCNT: No Space Left for temporary Undo错误发生的数量。

SQL> SELECT to_char(BEGIN_TIME, 'yy-mm-dd hh24:mi.ss') "Begin Time",
txncount "Transaction amt", maxconcurrency, undoblkcnt,
uscount "USCNT", nospaceerrcnt "NOSPEERRCNT" FROM v$tempundostat; Begin Time Transaction amt MAXCONCURRENCY UNDOBLKCNT USCNT NOSPEERRCNT
----------------- --------------- -------------- ---------- ---------- -----------
23-01-27 21:37.51 0 0 0 0 0
23-01-27 21:27.51 1 0 1 1 0
23-01-27 16:07.51 0 0 0 0 0

最新文章

  1. LINQ to Entities 和LINQ to Objects 的区别
  2. 自定义控件EditText
  3. 本地RUN页面时候,将异常直接显示出来,而不是乱码
  4. SQL生成随机数
  5. codeforces Gym 100187F F - Doomsday 区间覆盖贪心
  6. MVC bundles
  7. android cordova h5总结
  8. C++调用外部应用程序的方法的整理总结(常用)
  9. 【转】PV3D的小练习~太阳系八大行星
  10. 云计算---openstack各服务端口使用情况
  11. HTTP与HTTPs的区别?
  12. 【洛谷P1896】互不侵犯
  13. #7 //[CQOI2014]和谐矩阵
  14. Error: spawn EACCES
  15. Mac 上fopen总返回NULL
  16. FormatSQL
  17. Cognos 报表在列表上面显示汇总
  18. 浅析JavaScript访问对象属性和方法及区别
  19. centos-testlink安装使用手册
  20. RabbitMQ(6) 集群部署

热门文章

  1. 【调试】ftrace(一)基本使用方法
  2. android 投屏
  3. IDEA+java swing+MySQL配置
  4. JMeter 常用的几种断言方法
  5. 问题记录——nginx加载lua 模块,启动报错找不到 libluajit-5.1.so.2
  6. 零基础小白速成python?有了这本书你还在担心什么?
  7. Python算法教程_中文版书籍 程序员必备 免费下载
  8. 关于paddleocr2.6 布局分析的踩坑总结(一)
  9. Vuex 部分
  10. 浅谈storm