ocp听课总结之5——表空间

  1. 云栖社区>
  2. 博客>
  3. 正文

ocp听课总结之5——表空间

长烟慢慢 2012-02-16 10:49:12 浏览515
展开阅读全文

1、temp表空间:

temp表空间可以认为是PGA的SWAP区,这样就一下子明了了。PGA里放不下的都可以放到这个temp表空间中,来顺便回忆一下pga的结构,pga大致分为三个部分,分别是会话内存私有sql区游标和sql区(这个还不太了解。。。)这三个最重要的还是私有sql区,这部分区域占据了一个PGA的大部分空间,这里面有一个固定区域(persistent area)用来存储绑定的数据,还有就是运行时区域(runtime area)这是主要的工作区域,进行sort 、hash、还有位图的创建合并(bitmap merge/create).

 系统只有一个temp,大家都共用这个表空间,但是我们可以建立一个temp组,将多个temp表空间放到这个组中,temp是给谁用的?知道了吗?是给session用的,这作为PGA的swap也就理所当然了。

临时表空间可以有多个数据文件,还可以在一个temp里建组,增加多个临时表空间,这两方面对多个用户同时访问临时表空间提供了高并发。

临时表说明

   Temporary tables are useful in applications where a  result set must be buffered. For example, a scheduling application enables college students to create optional semester course schedules. Each schedule is represented by a row in a temporary table. During the session, the schedule data is private. When the student decides on a schedule, the application moves the row for the chosen schedule to a permanent table. At the end of the session, the schedule data in the temporary data is automatically dropped.


Temporary Table Creation

       The CREATE GLOBAL TEMPORARY TABLE statement creates a temporary table. The ON COMMIT clause specifies whether the table data is transaction-specific (default) or session-specific.

 

       Unlike temporary tables in some other relational databases, when you create a temporary table in an Oracle database, you create a static table definition. The temporary table is a persistent object described in the data dictionary, but appears empty until your session inserts data into the table. You create a temporary table for the database itself, not for every PL/SQL stored procedure.

 

       Because temporary tables are statically defined, you can create indexes for them with the CREATE INDEX statement. Indexes created on temporary tables are also temporary. The data in the index has the same session or transaction scope as the data in the temporary table. You can also create a view or trigger on a temporary table.

       -- 临时表可以创建临时的索引,视图,触发器。

 

Segment Allocation in Temporary Tables

       Like permanent tables, temporary tables are defined in the data dictionary. Temporary segments are allocated when data is first inserted. Until data is loaded in a session the table appears empty. Temporary segments are deallocated at the end of the transaction for transaction-specific temporary tables and at the end of the session for session-specific temporary tables.

 

 

    临时表只在Oracle 8i 以及以上产品中支持。ORACLE数据库除了可以保存永久表外,还可以建立临时表temporary tables。这些临时表用来保存一个会话SESSION的数据,或者保存在一个事务中需要的数据。当会话退出或者用户提交commit和回滚rollback事务的时候,临时表的数据自动清空,但是临时表的结构以及元数据还存储在用户的数据字典中。

 

Oracle的临时表创建之后基本不占用表空间,临时表并非存放在用户的表空间中,而是存放在 Schema 所指定的临时表空间中。如果你没有指定临时表(包括临时表的索引)存放的表空的时候,你插入到临时表的数据是存放在ORACLE系统的临时表空间中(TEMP)。

 

可以对临时表创建索引,视图,触发器,可以用export和import工具导入导出表的定义,但是不能导出数据。表的定义对所有的会话可见。建立在临时表上的索引也是临时的,也是只对当前会话或者事务有效. 

 

尽管对临时表的DML操作速度比较快,但同样也是要产生 Redo Log ,只是同样的DML语句,比对 PERMANENT 的DML 产生的Redo Log 少。

 

临时表的不足之处:

1.不支持lob对象,这也许是设计者基于运行效率的考虑,但实际应用中确实需要此功能时就无法使用临时表了。

2.不支持主外键关系

 

特性和性能(与普通表和视图的比较)

 1.临时表只在当前连接内有效

 2.临时表不建立索引,所以如果数据量比较大或进行多次查询时,不推荐使用

 3.数据处理比较复杂的时候时表快,反之视图快点

  4.在仅仅查询数据的时候建议用游标: open cursor for 'sql clause';

 

临时表的应用:

对于一个电子商务类网站,不同消费者在网站上购物,就是一个独立的 SESSION,选购商品放进购物车中,最后将购物车中的商品进行结算。也就是说,必须在整个SESSION期间保存购物车中的信息。同时,还存在有些消费者,往往最终结账时放弃购买商品。如果,直接将消费者选购信息存放在最终表(PERMANENT)中,必然对最终表造成非常大的压力。因此,对于这种案例,就可以采用创建临时表(ON COMMIT PRESERVE ROWS)的方法来解决。数据只在 SESSION 期间有效,对于结算成功的有效数据,转移到最终表中后,ORACLE自动TRUNCATE 临时数据;对于放弃结算的数据,ORACLE 同样自动进行 TRUNCATE ,而无须编码控制,并且最终表只处理有效订单,减轻了频繁的DML的压力。

Temp Table 的另一个应用,就是存放数据分析的中间数据。

 

 

二. 创建临时表

2.1  Creating a Temporary Table

       Temporary tables are useful in applications where a result set is to be buffered (temporarily persisted), perhaps because it is constructed by running multiple DML operations. For example, consider the following:

       A Web-based airlines reservations application allows a customer to create several optional itineraries. Each itinerary is represented by a row in a temporary table. The application updates the rows to reflect changes in the itineraries. When the customer decides which itinerary she wants to use, the application moves the row for that itinerary to a persistent table.

       During the session, the itinerary data is private. At the end of the session, the optional itineraries are dropped.

       The definition of a temporary table is visible to all sessions, but the data in a temporary table is visible only to the session that inserts the data into the table.

 

       Use the CREATE GLOBAL TEMPORARY TABLE statement to create a temporary table. The ON COMMIT clause indicates if the data in the table is transaction-specific (the default) or session-specific, the implications of which are as follows:

 

ON COMMIT Setting

Implications

DELETE ROWS

This creates a temporary table that is transaction specific. A session becomes bound to the temporary table with a transactions first insert into the table. The binding goes away at the end of the transaction. The database truncates the table (delete all rows) after each commit.

PRESERVE ROWS

This creates a temporary table that is session specific. A session gets bound to the temporary table with the first insert into the table in the session. This binding goes away at the end of the session or by issuing a TRUNCATE of the table in the session. The database truncates the table when you terminate the session.

 

This statement creates a temporary table that is transaction specific:

CREATE GLOBAL TEMPORARY TABLE admin_work_area
        (startdate DATE,
         enddate DATE,
         class CHAR(20))
      ON COMMIT DELETE ROWS;

 

       Indexes can be created on temporary tables. They are also temporary and the data in the index has the same session or transaction scope as the data in the underlying table.

       By default, rows in a temporary table are stored in the default temporary tablespace of the user who creates it. However, you can assign a temporary table to another tablespace upon creation of the temporary table by using the TABLESPACE clause of CREATE GLOBAL TEMPORARY TABLE. You can use this feature to conserve space used by temporary tables.

       For example, if you must perform many small temporary table operations and the default temporary tablespace is configured for sort operations and thus uses a large extent size, these small operations will consume lots of unnecessary disk space. In this case it is better to allocate a second temporary tablespace with a smaller extent size.

 

       The following two statements create a temporary tablespace with a 64 KB extent size, and then a new temporary table in that tablespace.

 

CREATE TEMPORARY TABLESPACE tbs_t1 
    TEMPFILE 'tbs_t1.f' SIZE 50m REUSE AUTOEXTEND ON
    MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL UNIFORM SIZE 64K;
 
CREATE GLOBAL TEMPORARY TABLE admin_work_area
        (startdate DATE,
         enddate DATE,
         class CHAR(20))
      ON COMMIT DELETE ROWS
      TABLESPACE tbs_t1;

 

 

 

2.2 创建临时表

Oracle临时表,有两种类型:

会话级的临时表

事务级的临时表。

 

2.2.1. 会话级的临时表

因为这这个临时表中的数据和你的当前会话有关系,当你当前SESSION不退出的情况下,临时表中的数据就还存在,而当你退出当前SESSION的时候,临时表中的数据就全部没有了,当然这个时候你如果以另外一个SESSION登陆的时候是看不到另外一个SESSION中插入到临时表中的数据的。即两个不同的SESSION所插入的数据是互不相干的。

当某一个SESSION退出之后临时表中的数据就被截断(truncate table,即数据清空)了。

注:这里要说明的是,ORACLE Truncate 掉的数据仅仅是分配给不同 Session 或 Transaction的 Temp Segment 上的数据,而不是将整张表数据 TRUNCATE 掉。当Commit的时候则数据还在,当Rollback的时候则数据也是一样被回滚.

 

会话级的临时表创建方法:

SQL>CREATE GLOBAL TEMPORARY TABLE TABLE_NAME (<column specification>)

ON COMMIT PRESERVE ROWS;

或者

SQL>CREATE GLOBAL TEMPORARY TABLE TABLE_NAME ON COMMIT PRESERVE ROWS AS SELECT * FROM TABLE_NAME;

 

示例:

SQL> CREATE GLOBAL TEMPORARY TABLE TT(ID NUMBER(2)) ON COMMIT PRESERVE ROWS ;

表已创建。

SQL> SELECT * FROM TT;

未选定行

SQL> INSERT INTO TT VALUES(1);

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM TT;

        ID

----------

         1

SQL> INSERT INTO TT VALUES(2);

已创建 1 行。

SQL> SELECT * FROM TT;

        ID

----------

         1

         2

SQL> ROLLBACK;

回退已完成。

SQL> SELECT * FROM TT;

        ID

----------

         1

 

2.2.2 事务特有的临时表(默认类型)

       该临时表与事务相关,当进行事务提交或者事务回滚的时候,临时表中的数据将自行被截断,其他的内容和会话级的临时表的一致(包括退出SESSION的时候,事务级的临时表也会被自动截断)。一旦COMMIT后,数据就被自动 TRUNCATE 掉了.

 

事务级临时表的创建方法:

SQL>CREATE GLOBAL TEMPORARY TABLE TABLE_NAME (<column specification>)

ON COMMIT DELETE ROWS;

 

或者

SQL>CREATE GLOBAL TEMPORARY TABLE TABLE_NAME ON COMMIT DELETE ROWS AS SELECT * FROM TABLE_NAME;

 

CREATE GLOBAL TEMPORARY TABLE TABLE_NAME;  在不指明类型的情况下默认为事务临时表。

 

SQL> CREATE GLOBAL TEMPORARY TABLE TT2(ID NUMBER(2)) ON COMMIT DELETE ROWS ;

表已创建。

SQL> SELECT * FROM TT2;

未选定行

SQL> INSERT INTO TT2 VALUES(1);

已创建 1 行。

SQL> SELECT * FROM TT2;

     ID

----------

     1

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM TT2;

未选定行


2、sysaux表空间:

 在Oracle 10g 版本中,引入了SYSTEM表空间的一个辅助表空间: SYSAUX表空间。

       SYSAUX 表空间存放一些其他的metadata组件,如OEM,Streams 等会默认存放在SYSAUX表空间里。这样也能降低SYSTEM表空间的负载。 因此SYSAUX 表空间也是在在DB 创建或者升级时自动创建的。 如果在手工使用SQL创建DB时没有指定SYSAUX tablespace,那么创建语句会报错。 无法执行。

       在正常操作下, 不能drop 和rename SYSAUX 表空间。 如果SYSAUX 表空间不可用时, 数据库的核心功能还是可以继续运行的。只是一些存放在SYSAUX表空间里的功能收到限制,就如我们之前说的OEM。

 

       在DB 创建时指定SYSAUX 表空间,必须指定如下4个属性:

(1).      PERMANENT      (永久的)

(2).      READ WRITE

(3).      EXTENT MANAGMENT LOCAL    (区本地管理)

(4).      SEGMENT SPACE MANAGMENT AUTO    (自动段空间管理)

 

       我们不能使用alter tablespace 来修改这4个属性,同样也不能drop 和rename SYSAUX 表空间。

       我们可以使用v$sysaux_occupants 视图来查看SYSAUX 表空间里的组件信息,如:

 

SQL> select occupant_name,schema_name,move_procedure from v$sysaux_occupants;

 

occupant_name           schema_name           move_procedure

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

logmnr                             system               sys.dbms_logmnr_d.set_tablespace

logstdby                           system               sys.dbms_logstdby.set_tablespace

streams                           sys

xdb                                     xdb                  xdb.dbms_xdb.movexdb_tablespace

ao                                      sys                  dbms_aw.move_awmeta

xsoqhist                            sys                  dbms_xsoq.olapimoveproc

xsamd                             olapsys              dbms_amd.move_olap_catalog

sm/awr                             sys

sm/advisor                      sys

sm/optstat                       sys

sm/other                          sys

statspack                      perfstat

odm                               dmsys                move_odm

sdo                                 mdsys                mdsys.move_sdo

wm                                  wmsys                dbms_wm.move_proc

ordim                             ordsys

ordim/plugins              ordplugins

ordim/sqlmm                si_informtn_schema

em                                 sysman               emd_maintenance.move_em_tblspc

text                                ctxsys               dri_move_ctxsys

ultrasearch                    wksys                move_wk

ultrasearch_demo_user  wk_test              move_wk

expression_filter            exfsys

em_monitoring_user      dbsnmp

tsm                                     tsmsys

job_scheduler                  sys

 

26 rows selected.

 

       这些组件占据这SYSAUX 表空间,所以这些组件的大小也就决定SYSAUX 表空间的大小。 根据这些组件创建时的初始化大小,SYSAUX 至少需要400M的空间。

 

       还有一点要注意,就是这里的schema_name 对应的是用户名。

 

SQL> desc dba_users;

 Name                                                 Null?                   Type

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

 USERNAME                                  NOT NULL      VARCHAR2(30)

 USER_ID                                      NOT NULL      NUMBER

 PASSWORD                                                           VARCHAR2(30)

 ACCOUNT_STATUS                  NOT NULL       VARCHAR2(32)

 LOCK_DATE                                                           DATE

 EXPIRY_DATE                                                       DATE

 DEFAULT_TABLESPACE          NOT NULL      VARCHAR2(30)

 TEMPORARY_TABLESPACE        NOT NULL     VARCHAR2(30)

 CREATED                                   NOT NULL            DATE

 PROFILE                                   NOT NULL            VARCHAR2(30)

 INITIAL_RSRC_CONSUMER_GROUP               VARCHAR2(30)

 EXTERNAL_NAME                                                    VARCHAR2(4000)

 

SQL> select username,account_status,default_tablespace from dba_users;

 

USERNAME      ACCOUNT_STATUS          DEFAULT_TABLESPA

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

MDDATA         EXPIRED & LOCKED                 USERS

MDSYS          EXPIRED & LOCKED                 SYSAUX

ORDSYS         EXPIRED & LOCKED                 SYSAUX

CTXSYS         EXPIRED & LOCKED                 SYSAUX

ANONYMOUS   EXPIRED & LOCKED                 SYSAUX

EXFSYS        EXPIRED & LOCKED                 SYSAUX

OUTLN         EXPIRED & LOCKED                   SYSTEM

DIP            EXPIRED & LOCKED                     USERS

DMSYS        EXPIRED & LOCKED                 SYSAUX

DBSNMP       OPEN                                        SYSAUX

SCOTT         EXPIRED & LOCKED                 USERS

WMSYS       EXPIRED & LOCKED                 SYSAUX

SYSMAN      OPEN                                           SYSAUX

XDB           EXPIRED & LOCKED                   SYSAUX

TSMSYS        EXPIRED & LOCKED               USERS

ORDPLUGINS    EXPIRED & LOCKED         SYSAUX

MGMT_VIEW     OPEN                                     SYSTEM

SI_INFORMTN_SCHEMA  EXPIRED & LOCKED            SYSAUX

OLAPSYS        EXPIRED & LOCKED                 SYSAUX

SYS            OPEN                             SYSTEM

SYSTEM        OPEN                             SYSTEM

 

21 rows selected.

 

       这里没有显示这些组件的描述信息,因为显示不全。 感兴趣的,可以自己查看一下。

SQL> desc v$sysaux_occupants

 Name                                      Null?    Type

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

 OCCUPANT_NAME                                      VARCHAR2(64)

 OCCUPANT_DESC                                      VARCHAR2(64)

 SCHEMA_NAME                                        VARCHAR2(64)

 MOVE_PROCEDURE                                     VARCHAR2(64)

 MOVE_PROCEDURE_DESC                                VARCHAR2(64)

 SPACE_USAGE_KBYTES                                 NUMBER

 

       在v$sysaux_occupants 视图里有个move_procudure的过程。 这个过程就是用迁移组件信息的。就是对于已经安装好的组件,如果我们想把这些组件放到其他的空间,就可以使用这个存储过程。如果没有对应的过程,就不可移动。

       这样做可以控制SYSAUX表空间的大小。 比如我们的AWR。 AWR 是SYSAUX 中占用空间最多的组件。 对于一个有10个并发session 的系统,就需要200M 的空间。当然,也可以修改AWR的保存策略来控制AWR所占用空间的大小。

 

示例:

 

2.1. Logminer SYSAUX 表空间,迁移到users表空间,在还原回来

 

1)查看之前的信息:

SQL> select OCCUPANT_NAME,OCCUPANT_DESC,SCHEMA_NAME,MOVE_PROCEDURE,SPACE_USAGE_KBYTES from v$sysaux_occupants where occupant_name='LOGMNR';

 

OCCUPANT_NAME   OCCUPANT_DESC   SCHEMA_NAME          MOVE_PROCEDURE                               SPACE_USAGE_KBYTES

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

LOGMNR                        LogMiner                           SYSTEM               SYS.DBMS_LOGMNR_D.SET_TABLESPACE                       6080


2)移动

 

SQL> exec SYS.DBMS_LOGMNR_D.SET_TABLESPACE('USERS');

PL/SQL procedure successfully completed.

 

3)验证

SQL>  select OCCUPANT_NAME,OCCUPANT_DESC,SCHEMA_NAME,MOVE_PROCEDURE,SPACE_USAGE_KBYTES from v$sysaux_occupants where occupant_name='LOGMNR';

 

OCCUPANT_NAME   OCCUPANT_DESC   SCHEMA_NAME          MOVE_PROCEDURE                           SPACE_USAGE_KBYTES

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

LOGMNR          LogMiner        SYSTEM               SYS.DBMS_LOGMNR_D.SET_TABLESPACE                          0

--注意,这里占空的空间变成了0. 数据迁移到了USERS 表空间

4)还原到SYSAUX 表空间

SQL>  exec SYS.DBMS_LOGMNR_D.SET_TABLESPACE('SYSAUX');

PL/SQL procedure successfully completed.

 

5)验证

SQL> select OCCUPANT_NAME,OCCUPANT_DESC,SCHEMA_NAME,MOVE_PROCEDURE,SPACE_USAGE_KBYTES from v$sysaux_occupants where occupant_name='LOGMNR';

 

OCCUPANT_NAME   OCCUPANT_DESC   SCHEMA_NAME          MOVE_PROCEDURE                           SPACE_USAGE_KBYTES

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

LOGMNR          LogMiner        SYSTEM               SYS.DBMS_LOGMNR_D.SET_TABLESPACE                       6080

--大小又变回来了。

 

2.2  SYSAUX不能drop

 

SQL> drop tablespace SYSAUX including contents and datafiles;

drop tablespace SYSAUX including contents and datafiles

*

ERROR at line 1:

ORA-13501: Cannot drop SYSAUX tablespace

 

 

2.3 SYSAUX 不能重命名

SQL> alter tablespace SYSAUX rename to DAVE;

alter tablespace SYSAUX rename to DAVE

*

ERROR at line 1:

ORA-13502: Cannot rename SYSAUX tablespace

 

2.3 不能将SYSAUX 改成只读

 

SQL> alter tablesapce SYSAUX read only;

alter tablesapce SYSAUX read only

      *

ERROR at line 1:

ORA-00940: invalid ALTER command

3、undo表空间:

Oracle Undo有两种方式: 一是使用undo 表空间,二是使用回滚段

 

  我们通过 undo_management 参数来控制使用哪种方式,如果设为auto就使用UNDO 表空间,这时必须要指定一个UNDO 表空间。 如果设为manual系统启动后使用rollback segment方式存储undo信息。如果系统没有指定undo_management,那么系统默认以manual方式启动,即使设置了auto方式的参数,这些参数将被忽略。

当实例启动的时候,系统自动选择第一个有效的undo表空间或者是rollback segment如果没有有效的可用的undo表空间或者是回滚段,系统使用system rollback segment这种情况是不被推荐的,当系统运行在没有undo的情况下,系统会在alert.log中记录一条警告信息

SQL> show parameter undo

NAME                   TYPE        VALUE

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

undo_management            string      AUTO

undo_retention             integer     900

undo_tablespace            string      UNDOTBS1

参考:Oracle undo 管理

http://blog.csdn.net/changyanmanman/article/details/7391901

 

一. UNDO 表空间

下面来看一下undo 的表空间管理。先来查看一下表空间的使用情况:

/* Formatted on 2010/6/23 9:46:58 (QP5 v5.115.810.9015) */

SELECT   a.tablespace_name,

         ROUND (a.total_size) "total_size(MB)",

         ROUND (a.total_size) - ROUND (b.free_size, 3) "used_size(MB)",

         ROUND (b.free_size, 3) "free_size(MB)",

         ROUND (b.free_size / total_size * 100, 2) || '%' free_rate

  FROM   (  SELECT   tablespace_name, SUM (bytes) / 1024 / 1024 total_size

              FROM   dba_data_files

          GROUP BY   tablespace_name) a,

         (  SELECT   tablespace_name, SUM (bytes) / 1024 / 1024 free_size

              FROM   dba_free_space

          GROUP BY   tablespace_name) b

 WHERE   a.tablespace_name = b.tablespace_name(+);


TABLESPACE_NAME    total_size(MB) used_size(MB) free_size(MB) FREE_RATE

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

SYSAUX                            580       545.187        34.813  6%

UNDOTBS1                       90        23.875        66.125  73.47%

DAVE                                 20          6.25         13.75  68.75%

USERS                                10         8.375         1.625  16.25%

SYSTEM                             960       951.062         8.938  93%

从结果我们看到UNDO 表空间已经用了23.875M。 我们看一下这使用的23M空间里空闲和非空闲比例:

/* Formatted on 2010/6/23 9:49:53 (QP5 v5.115.810.9015) */

  SELECT   tablespace_name, status, SUM (bytes) / 1024 / 1024 "Bytes(M)"

    FROM   dba_undo_extents

GROUP BY   tablespace_name, status;

TABLESPACE_NAME      STATUS      Bytes(M)

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

UNDOTBS1             UNEXPIRED     9.1875

UNDOTBS1             EXPIRED      13.6875

我们看一下查询的结果,UNEXPIRED EXPIRED 是已使用的undo 表空间,其中expired 说明是已经过期的数据,也就是15分钟(默认情况)以外的数据,以被覆盖可以认为是空闲的

在此补充一点知识:

采用UNDO 表空间时,会有一个参数UNDO_RETENTION该参数用来指定undo 记录保存的最长时间,以秒为单位,是个动态参数,完全可以在实例运行时随时修改,通常默认是900 秒,也就是15 分钟。

undo_retention 只是指定undo 数据的过期时间,并不是说,undo 中的数据一定会在undo表空间中保存15 分钟,比如说刚一个新事务开始的时候,如果undo 表空间已经被写满,则新事务的数据会自动覆盖已提交事务的数据,而不管这些数据是否已过期,因此呢,这就又关联回了第一点,当你创建一个自动管理的undo 表空间时,还要注意其空间大小,要尽可能保证undo 表空间有足够的存储空间。

undo_retention 中指定的时间一过,已经提交事务中的数据就立刻无法访问,它只是失效,只要不被别的事务覆盖,它会仍然存在,并可随时被flashback 特性引用。如果你的undo表空间足够大,而数据库又不是那么繁忙,那么其实undo_retention 参数的值并不会影响到你,哪怕你设置成1,只要没有事务去覆盖undo 数据,它就会持续有效。因此呢,这里还是那句话,要注意undo 表空间的大小,保证其有足够的存储空间。

只有在一种情况下,undo 表空间能够确保undo 中的数据在undo_retention 指定时间过期前一定有效,就是为undo 表空间指定Retention Guarantee,指定之后,oracle 对于undo 表空间中未过期的undo 数据不会覆盖,例如:

SQL> Alter tablespace undotbs1 retention guarantee;

 

禁止undo 表空间retention guarantee例如:

SQL> Alter tablespace undotbs1 retention noguarantee;

总结一下:

UNDO 表空间是会被重用的,只有当事务没结束,开了retention guarantee,或在undo_retention时间内不能被重用

undo_retention规定的时间内,数据都是有效的,过期后都会设为无效,状态被改为Expired,这些回滚段将会被看作Free Space。但是只要数据没有被覆盖就可以使用。如果空间已满,新事务的数据会自动覆盖掉已经提交的事务数据,即使在undo_retention的时间内。除非指定Retention Guarantee模式,才能保证在undo_retention内不被覆盖。

二. UNDO 表空间满了的处理方法

2.1 先模拟UNDO 表空间满的情况


SQL>  alter system set undo_retention=10800; -- 3个小时
系统已更改。
SQL> create undo tablespace undo datafile 'F:/backup/undo.dbf' size 1m ;
表空间已创建。
SQL> alter tablespace undo retention guarantee;
表空间已更改。
SQL> alter system set undo_tablespace=undo;
系统已更改。

SQL> create table DBA(id number);

表已创建。
SQL> begin

  2  for i in 1 .. 100000 loop

  3  insert into dba values(i);

  4  commit;

  5  end loop;

  6  end;

  7  /

begin

*

第 行出现错误:

ORA-30036: 无法按 扩展段 (在还原表空间 'UNDO' )

ORA-06512: 在 line 3

2.2 处理方法

处理方法有两种,一是添加undo 表空间的数据文件,二是切换UNDO tablespace. 这种情况下多用在undo 表空间已经非常大的情况。 

2.2.1 增加数据文件

SQL> ALTER TABLESPACE undo ADD DATAFILE 'F:/backup/undo02.dbf' size 100M reuse;

表空间已更改。

SQL> begin

  2  for i in 1..100000 loop

  3  insert into dba values(1);

  4  commit;

  5  end loop;

  6  end;

  7  /

PL/SQL 过程已成功完成。

2.2.2 切换UNDO 表空间

1、建立新的表空间UNDOTBS2

SQL> CREATE UNDO TABLESPACE UNDOTBS2 DATAFILE 'F:/backup/undo03.dbf' size 100M reuse;

表空间已创建。

2、切换到新建的UNOD表空间上来,操作如下
SQL> alter system set undo_tablespace=UNDOTBS2 scope=both;

系统已更改。

3、将原来的UNDO表空间,置为脱机:
SQL> alter tablespace UNDO offline;

表空间已更改。

4、删除原来的UNDO表空间:
SQL> drop tablespace UNDO including contents AND DATAFILES CASCADE CONSTRAINTS ;

表空间已删除。

如果只是drop tablespace UNDO ,则只会在删除控制文件里的记录,并不会物理删除文件。 

Drop undo表空间的时候必须是在未使用的情况下才能进行。如果undo表空间正在使用(例如事务失败,但是还没有恢复成功),那么drop表空间命令将失败。在drop表空间的时候可以使用including contents

 

三. UNDO 表空间损坏的恢复方法

一般Undo 表空间损坏的情况下,数据库都已不能正常打开了。启动时都会报类似如下的错误:

ORA-01157: cannot identify/lock data file 12 - see DBWR trace file

ORA-01110: data file 12: '/d01/oramtest/proddata/undo01.dbf'

 要想解决问题,必须重建UNDO 表空间,但是如果不open, 就不能重建创建undo 表空间。 所以可以先用系统默认的undo 表空间:system rollback segment 来启动数据库,再创建UNDO 表空间。

3.1 创建pfile 文件

SQL> create pfile='F:/initorcl.ora' from spfile;

文件已创建。
3.2 修改pfile文件
#*.undo_tablespace='UNDOTBS1'

#*.undo_management='AUTO'

undo_management='MANUAL'

rollback_segments='SYSTEM'

3.3 启动数据库至Mount 状态

SQL> STARTUP MOUNT pfile='F:/initorcl.ora' ;

3.4 offline drop undo 表空间

 SQL> ALTER DATABASE DATAFILE 'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF' OFFLINE DROP; 

3.5 open 数据库

SQL> ALTER DATABASE OPEN;

3.6 删除旧的undo 表空间

SQL> DROP TABLESPACE UNDOTBS1 INCLUDING CONTENTS;   

注:该命令不会删除物理文件。 要想一起删除物理文件需要 AND DATAFILES CASCADE CONSTRAINTS ;

如:  drop tablespace UNDOTBS1 including contents AND DATAFILES CASCADE CONSTRAINTS ;

3.7 创建新的UNDO 表空间

SQL> create undo tablespace undotbs1 datafile 'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF' size 100M ;

create undo tablespace undotbs1 datafile 'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF' size 100M

*

第 行出现错误:

ORA-01119: 创建数据库文件 'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF'时出错

ORA-27038: 所创建的文件已存在

OSD-04010: 指定了 <create> 选项但文件已经存在

因为我们之前删除时并没有删除物理文件,所以在建同名文件时就会报错。 我们可以加上REUSE 参数。 只要文件不在使用,就可以重写已经存在的文件。 

SQL> create undo tablespace undotbs1 datafile 'D:/app/Administrator/oradata/orcl/UNDOTBS01.DBF' size 100M reuse;

表空间已创建。

3.8  shutdown 数据库 并将pfile 改回

SQL> select name,issys_modifiable from v$parameter where name='undo_management' or name='rollback_segments';

NAME             ISSYS_MOD

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

rollback_segments    FALSE

undo_management    FALSE

从上面查询的结果,可以知道修改这2个参数必须重启数据,所以还是shutdown 吧。 

SQL> shutdown immediate

3.9 修改pfile 参数

*.undo_tablespace='UNDOTBS1'

*.undo_management='AUTO'

#undo_management='MANUAL'

#rollback_segments='SYSTEM'

3.10 用刚才修改的pfile 启动数据库,并创建spfile

SQL> startup pfile='F:/initorcl.ora' ;

SQL> create spfile from pfile='F:/initorcl.ora';

3.10 再次shutdown,用spfile 启动

SQL> shutdown immediate

SQL> startup

 

一般数据文件损坏的情况也可以采用类似的方法, 先启动到mount, 在将损坏的数据文件offline drop。 在open 数据库,drop 掉损坏的数据文件。 当然这种做法有数据丢失。 能恢复的话,尽量恢复。 


4、表空间的几种状态:

read write

read only

要把一个表空间变为read only的,首先满足一下条件:1、表空间必须是online的,没有undo信息需要



offline

offline的几种模式介绍: ALTER TABLESPACE users OFFLINE NOMAL | TEMPROAY | IMMEDIATE.

nomal:除非是表空间损坏的情况下,否则一律用nomal模式离线。nomal的意思是在离线的时候,oracle做一个checkpoint操作,将这个表空间内文件对应的脏块全部从buffer中写入到文件中去,下次重用这个表空间内的文件时不需要任何恢复。

temporay:只有在使用momal命令不起作用时才可以使用这个参数。假如一个表空间内有5个数据文件,有三个能用的,两个不能用的(已损坏),用这个temporay离线的时候就把能用的三个数据文件的脏块全部写入(对着三个可用文件做checkpoint),这样相对来说还是比较好的,能写多少就写多少,保证了最少损失。。下次再把这个表空间online的之前,要先把那两个坏的文件做介质恢复。

immediate:不管你这个文件是否还能用,直接offline,不会在各个数据文件上执行检查点操作,所以下次在用的时候肯定 需要日志做实例恢复。如果数据库是noarchivelog模式的,此操作不能执行。

相老师说在9i以前,如果你做过alter database open resetlogs,那这个表空间就废了,不能恢复了。。。非常危险哦亲。。



4、将输出结果存储到文件:

首先在我的随便一个路径下建立一个文件,如我的:touch /home/oracle/liutemp/out.txt .好了,待会就把要查询的数据输出到这个out.txt 文件中。

打开sqlplus,输入命令:

spool /home/oracle/liutemp/out.txt ;

select * from v$parameter;——这句是要输出的查询语句

spool off; ——结束。

现在可以到out.txt文件中看看输出的结果了。


不删除文件,清空文件内容命令
   
      在某些时候,需要清空文件内容,而不删除文件。比喻有些日志文件(log.txt);在linux下的命令为:true >log.txt
测试结果:
touch  log.txt  →#新建文件log.txt
vi  log.txt       →#编辑文件
 随便输入什么东西
:wq!回车  →#保存退出;
cat log.txt       →#查看 文件内容;
true >log.txt   →#查看文件里面的内容;

网友评论

登录后评论
0/500
评论
长烟慢慢
+ 关注