Oracle 回滚 ROLLBACK 和撤销 UNDO

               

--==================================

--Oracle 回滚(ROLLBACK)和撤销(UNDO)

--==================================

 

一、回滚(ROLLBACK)和撤销(UNDO)

 

    回滚和前滚是保证Oracle数据库中的数据处于一致性状态的重要手段。

   

    9i版本以前

        Oracle使用数据库中的回滚段来实现未提交数据或因系统故障导致实例崩溃时进行回滚操作

        每一个表空间需要创建回滚段,各个表空间对回滚段实现各自的管理

扫描二维码关注公众号,回复: 5055669 查看本文章

    9i及后续版本

        提供了一种新的回滚数据的管理方式,即使用Oracle自动管理的撤销(Undo)表空间

        自动撤销管理表空间统一管理所有DML的回滚操作,简化了对于回滚工作的管理

        在9i,10g中的回滚段仅仅用作保留向后兼容

        撤销段代替了原有版本中的回滚段,因此本文所有描述均使用撤销

   

    撤销的实质意味着将所作的修改退回到修改前的状态,即倒退所有DML语句

       

二、撤销段中的内容及相关特性

    对于任何DML操作而言,必须同时处理数据块和撤销块,并且还会生成重做信息

    ACID中,ACI要求生成撤销,D则要求生成重做

    INSERT

        撤销段记录插入记录的rowid,如果需要撤销,则根据rowid将该记录删除即可

    UPDATE:

        撤销段记录被更新字段的原始值,撤销时将原始值覆盖新值即可

    DELETE

        撤销段记录整行的数据,撤销时执行反向操作将该记录插入原表

 

    由上可知,UNDO段中的内容总结如下:

        数据为修改之前的副本

        从每个改变数据的事务中获得

        在事务结束前一直被保留

   

    UNDO中数据的作用:

        用于回滚操作

        读一致性和闪回查询

        用于事务失败时的恢复

       

    UNDO段与事务:

        一个事物的启动,Oracle将为其分配仅仅一个UNDO,若该段用完,Oracle会自动为该UNDO段添加另一个区间(extent)

        一个UNDO段能够同时为多个事务服务

       

    UNDO段与UNDO表空间:

        UNDO段中的内容存储在UNDO表空间

        任意给定时刻只能使用一个UDNO表空间

        UNDO表空间必须被创建为持久的、本地管理、可自动扩展的表空间

        正在使用的UNDO表空间不能撤销或删除

        UNDO表空间使用循环写的方式,与联机日志文件写相似,不同的是UNDO中可以设置了undo_retention 保留时间

   

    UNDO段的两种管理方式:

        AUTO    自动管理(推荐)

        MANUAL  手动管理(仅保留)

           

三、与撤销相关的几个参数

    --查看本机中Oracle的版本

        SQL> SELECT * FROM v$version;

 

        BANNER

        ----------------------------------------------------------------

        Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

        PL/SQL Release 10.2.0.1.0 - Production

        CORE    10.2.0.1.0      Production

        TNS for Linux: Version 10.2.0.1.0 - Production

        NLSRTL Version 10.2.0.1.0 - Production

 

    --查看和UNDO相关的参数

        SQL> SHOW PARAMETER undo;

 

        NAME                                 TYPE        VALUE

        ------------------------------------ ----------- ------------------------------

        undo_management                      string      MANUAL

        undo_retention                       integer     900

        undo_tablespace                      string      UNDOTBS1

           

    undo_management

        设置数据库的撤销段是否使用自动管理模式,值可以为automanual,当为manual时将不使用撤销段,即不使用自动管理模式

        该参数为静态参数,修改后需重启实例才能生效

       

    undo_retention

        指定撤销段数据在undo段中为非活动状态后被覆盖前保留的时间,单位为秒。在undo_managementauto时生效,为动态参数

       

    undo_tablespace

        指定使用哪个表空间来实现数据的撤销,在undo_managementauto时生效,为动态参数

       

    retention guarantee子句:

        保证撤销保留,使用下面的操作来实现

            ALTER TABLESPACE undo_tablespace_name RETENTION GUARANTEE;

 

    --下面的查询中是当undo_managementmanual时的结果集,可以看出撤销表空间的撤销段都处于offline状态   

        SQL> SELECT segment_name,tablespace_name,status FROM dba_rollback_segs;

 

        SEGMENT_NAME                   TABLESPACE_NAME                STATUS

        ------------------------------ ------------------------------ ----------------

        SYSTEM                         SYSTEM                         ONLINE

        _SYSSMU1$                      UNDOTBS1                       OFFLINE

        _SYSSMU2$                      UNDOTBS1                       OFFLINE

        _SYSSMU3$                      UNDOTBS1                       OFFLINE

        _SYSSMU4$                      UNDOTBS1                       OFFLINE

        _SYSSMU5$                      UNDOTBS1                       OFFLINE

        _SYSSMU6$                      UNDOTBS1                       OFFLINE

        _SYSSMU7$                      UNDOTBS1                       OFFLINE

        _SYSSMU8$                      UNDOTBS1                       OFFLINE

        _SYSSMU9$                      UNDOTBS1                       OFFLINE

        _SYSSMU10$                     UNDOTBS1                       OFFLINE

 

 

    --undo_management 参数为manual时,对scott.emp插入一条新记录,收到了错误提示

    --非系统表空间不能够使用回滚段

        SQL> INSERT INTO scott.emp(empno,ename,salary)

          2  VALUES(6666,'Jenney',3000);

        INSERT INTO scott.emp(empno,ename,salary)

                          *

        ERROR at line 1:

        ORA-01552: cannot use system rollback segment for non-system tablespace 'USERS'

 

    --查看段的类型,发现仅仅system表空间存在ROLLBACK 段,所以前一条插入语句收到错误提示

        SQL> SELECT DISTINCT segment_type,tablespace_name FROM dba_segments

          2  ORDER BY tablespace_name;

 

        SEGMENT_TYPE       TABLESPACE_NAME

        ------------------ ------------------------------

        INDEX              EXAMPLE

        INDEX PARTITION    EXAMPLE

        LOBINDEX           EXAMPLE

        LOBSEGMENT         EXAMPLE

        NESTED TABLE       EXAMPLE

        TABLE              EXAMPLE

        TABLE PARTITION    EXAMPLE

        INDEX              SYSAUX

        INDEX PARTITION    SYSAUX

        LOB PARTITION      SYSAUX

        LOBINDEX           SYSAUX

 

        SEGMENT_TYPE       TABLESPACE_NAME

        ------------------ ------------------------------

        LOBSEGMENT         SYSAUX

        NESTED TABLE       SYSAUX

        TABLE              SYSAUX

        TABLE PARTITION    SYSAUX

        CLUSTER            SYSTEM

        INDEX              SYSTEM

        LOBINDEX           SYSTEM

        LOBSEGMENT         SYSTEM

        NESTED TABLE       SYSTEM

        ROLLBACK           SYSTEM       --与之前的版本兼容的回滚段

        TABLE              SYSTEM

 

        SEGMENT_TYPE       TABLESPACE_NAME

        ------------------ ------------------------------

        TABLE              TBS1

        TYPE2 UNDO         UNDOTBS1     --9i之后使用的撤销段

        INDEX              USERS

        LOBINDEX           USERS

        LOBSEGMENT         USERS

        NESTED TABLE       USERS

        TABLE              USERS

 

        --下面将undo_management改为支持自动管理,需要重启实例

        SQL> ALTER SYSTEM SET undo_management = 'auto' SCOPE = SPFILE;

 

        System altered.

 

        SQL> SHUTDOWN IMMEDIATE;

        Database closed.

        Database dismounted.

        ORACLE instance shut down.

        SQL> STARTUP;

        ORACLE instance started.

 

        Total System Global Area  251658240 bytes

        Fixed Size                  1218796 bytes

        Variable Size              67110676 bytes

        Database Buffers          180355072 bytes

        Redo Buffers                2973696 bytes

        Database mounted.

        Database opened.

 

    --再次查看dba_rollback_segs视图所有的撤销段全部处于online状态

    --注意第一行为system表空间的撤销段,用于系统表空间的撤销

        SQL> SELECT segment_name,tablespace_name,status FROM dba_rollback_segs;

 

        SEGMENT_NAME                   TABLESPACE_NAME                STATUS

        ------------------------------ ------------------------------ ----------------

        SYSTEM                         SYSTEM                         ONLINE 

        _SYSSMU1$                      UNDOTBS1                       ONLINE

        _SYSSMU2$                      UNDOTBS1                       ONLINE

        _SYSSMU3$                      UNDOTBS1                       ONLINE

        _SYSSMU4$                      UNDOTBS1                       ONLINE

        _SYSSMU5$                      UNDOTBS1                       ONLINE

        _SYSSMU6$                      UNDOTBS1                       ONLINE

        _SYSSMU7$                      UNDOTBS1                       ONLINE

        _SYSSMU8$                      UNDOTBS1                       ONLINE

        _SYSSMU9$                      UNDOTBS1                       ONLINE

        _SYSSMU10$                     UNDOTBS1                       ONLINE

 

 

    由上面的示例可知:

        ROLLBACK 段:      --与之前的版本兼容的回滚段

        TYPE2 UNDO 段:    --9i之后使用的撤销段

        关于回滚,一个时刻仅能使用一种类段类型,即要么使用与以前版本兼容的回滚段,要么使用撤销段

        事实上,在9i之后仅仅支持撤销段,从上面错误的提示即可证实

 

    --查看DML语句产生的事务

        SQL> SHOW USER;                                   

        USER is "SYS"

        SQL> SELECT * FROM scott.emp WHERE ename = 'SCOTT';

 

             EMPNO ENAME           JOB              MGR HIREDATE      SALARY     DEPTNO

        ---------- --------------- --------- ---------- --------- ---------- ----------

              7788 SCOTT           ANALYST         7566 19-APR-87       3500         20

             

        SQL> UPDATE scott.emp SET sal = sal * 2 WHERE  ename = 'SCOTT';

 

        1 row updated.

 

        SQL> SELECT addr,xidusn,status,start_time,used_ublk

          2  FROM v$transaction;

 

猜你喜欢

转载自blog.csdn.net/uffvhj/article/details/86625172