Chinaunix首页 | 论坛 | 博客
  • 博客访问: 116344
  • 博文数量: 28
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 205
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-12 15:22
个人简介

没有挫败,只有暂未成功而已。

文章分类

全部博文(28)

文章存档

2018年(28)

我的朋友

分类: Oracle

2018-10-24 14:31:19

一、本文说明

    本文整理于谭大师的让Oracle跑得更快1。

二、只读表空间与数据备份和恢复的关系

    表空间设置成只读之后,只需要执行一次备份操作即可,在后续备份时不再需要考虑这些表空间的备份。

    原因很容易理解,这些表空间中的数据已经不再改变,存储在表空间中的数据状态始终保持在表空间设置为Read-Only那一刻,就像是给表空间做了一个快照一样,Oracle也不需要对它们进行额外的恢复工作,比如应用归档。

    看下面的例子:

    我们创建两个表空间,一个是只读(Read-Only)的,一个是常规的(Read-Write),下面来比较这两个表空间数据文件的变化情况。

复制代码
 1 SQL> create tablespace readonly datafile '/u01/app/oracle/oradata/readonly01.dbf' size 10m;  2  3 Tablespace created.  4  5 SQL> create tablespace readwrite datafile '/u01/app/oracle/oradata/readwrite01.dbf' size 10m;  6  7 Tablespace created.  8  9 SQL> alter tablespace readonly read only; 10 11 Tablespace altered.
复制代码

    这样,我们就创建了两个表空间readonly和readwrite,并把表空间readonly的状态设置为只读。

1 SQL> select name,file#,checkpoint_change# from v$datafile where name like '%read%'; 2 3 NAME FILE# CHECKPOINT_CHANGE# 4 --------------------------------------------- ---------- ------------------ 5 /u01/app/oracle/oradata/readonly01.dbf 6 4342263 6 /u01/app/oracle/oradata/readwrite01.dbf 7 4341997

    我们先记录下当前状态下两个表空间数据文件的SCN号,这个号表示表空间数据文件在Oracle数据库运行时某个时间点的状态。SCN是Oracle里面的一个序号,用来标识一个先后顺序,通常用于保护数据块的完整性或者一致性的查询。
当数据块做了修改,它的SCN值就会发生相应的改变。

1 SQL> alter system checkpoint; 2 3 System altered.

    我们发出一个CHECKPOINT命令,这个命令实际上是将内存中的脏数据块写入到磁盘上的文件中,并更新文件头部信息,以保证数据块中数据的一致性。

1 SQL> select name,file#,checkpoint_change# from v$datafile where name like '%read%'; 2 3 NAME FILE#   CHECKPOINT_CHANGE# 4 --------------------------------------------- ---------- ------------------ 5 /u01/app/oracle/oradata/readonly01.dbf 6 4342263 6 /u01/app/oracle/oradata/readwrite01.dbf 7 4343696

    我们看到,执行了CHECKPOINT命令之后,READWRITE表空间数据文件的SCN号发生了变化,这说明这个表空间相比之前的状态,它的数据文件已经产生了变化。
尽管我们没有对这个表空间做任何操作,但不能保证Oracle不这样做(实际上,这里是表空间数据文件的文件头数据块产生了变化)。我们知道,只要数据文件的SCN号发生了变化,Oracle就需要进行恢复;而这里,READONLY的SCN号并没有变化,看起来就像静止在那里一样。

    这就是说,如果此时Oracle数据库出现问题,比如DOWN掉了,在数据库重新OPEN时,READONLY表空间是不需要恢复的,因为它的状态依然保持在将它置于READ-ONLY那一刻,那一刻数据库是好的。

    而READWRITE表空间就不同了,如果此时数据库DOWN掉了,它就需要进行恢复,因为这个表空间上的数据块状态是持续更新的,它需要通过联机日志(或者归档日志)将它恢复到最后Oracle数据库DOWN掉时的状态。

    我们继续来看,现在将这两个表空间的状态改为离线。

复制代码
 1 SQL> alter tablespace readonly offline;  2  3 Tablespace altered.  4  5 SQL> alter tablespace readwrite offline;  6  7 Tablespace altered.  8  9 SQL> col name for a45; 10 SQL> select name,file#,checkpoint_change# from v$datafile where name like '%read%'; 11 12 NAME FILE#   CHECKPOINT_CHANGE# 13 --------------------------------------------- ---------- ------------------ 14 /u01/app/oracle/oradata/readonly01.dbf 6 4342263 15 /u01/app/oracle/oradata/readwrite01.dbf 7 4351566
复制代码

    我们看到,READONLY表空间的SCN号依然保持不变。

复制代码
 1 SQL> alter system checkpoint;  2  3 System altered.  4  5 SQL> select name,file#,checkpoint_change# from v$datafile where name like '%read%';  6  7 NAME FILE#    CHECKPOINT_CHANGE#  8 --------------------------------------------- ---------- ------------------  9 /u01/app/oracle/oradata/readonly01.dbf 6 4342263 10 /u01/app/oracle/oradata/readwrite01.dbf 7 4351566
复制代码

    当数据文件状态为离线时,不论之前它是只读还是读写表空间,它的状态都不再改变。

    现在,我们把这两个表空间的状态重新改为在线。

复制代码
 1 SQL> alter tablespace readonly online;  2  3 Tablespace altered.  4  5 SQL> alter tablespace readwrite online;  6  7 Tablespace altered.  8  9 SQL> select name,file#,checkpoint_change# from v$datafile where name like '%read%'; 10 11 NAME FILE#    CHECKPOINT_CHANGE# 12 --------------------------------------------- ---------- ------------------ 13 /u01/app/oracle/oradata/readonly01.dbf 6 4342263 14 /u01/app/oracle/oradata/readwrite01.dbf 7 4351660
复制代码

    我们看到,READWRITE表空间的SCN号再次改变了。实际上,在把READWRITE表空间的状态改为在线时,Oracle对它进行了恢复操作,使它的状态和数据库当前状态一致;而READONLY表空间依然静止不动地保持着它最初的状态,和数据库的变化毫无关系。
这样看来,在备份和恢复上,对只读表空间备份一次就够了;而对其他的读写表空间的备份,可能需要定期做全备份或者增量备份,同时还需要备份恢复时所需要的归档日志。这些备份集不但需要大量的磁盘空间,而且恢复时也可能会相当耗时。

在这里有一个专题是讨论只读表空间的恢复的: 《只读数据文件损坏恢复》

三、只读表空间对于数据库的启动和关闭的影响

    将不再有数据变化的一些表空间置于Read-Only状态,可以加快数据库关闭和启动的时间,原因是Oracle不会再对设置为Read-Only状态的表空间的数据文件进行处理;或者说,在数据同步(数据块从内存刷新到磁盘上)时,忽略这些文件。

复制代码
 1 SQL> create tablespace test datafile '/u01/app/oracle/oradata/test01.dbf' size 10m,  2 2 '/u01/app/oracle/oradata/test02.dbf' size 10m,  3 3 '/u01/app/oracle/oradata/test03.dbf' size 10m,  4 4 '/u01/app/oracle/oradata/test04.dbf' size 10m,  5 5 '/u01/app/oracle/oradata/test05.dbf' size 10m,  6 6 '/u01/app/oracle/oradata/test06.dbf' size 10m,  7 7 '/u01/app/oracle/oradata/test07.dbf' size 10m,  8 8 '/u01/app/oracle/oradata/test08.dbf' size 10m,  9 9 '/u01/app/oracle/oradata/test09.dbf' size 10m, 10 10 '/u01/app/oracle/oradata/test10.dbf' size 10m, 11 11 '/u01/app/oracle/oradata/test11.dbf' size 10m, 12 12 '/u01/app/oracle/oradata/test12.dbf' size 10m, 13 13 '/u01/app/oracle/oradata/test13.dbf' size 10m, 14 14 '/u01/app/oracle/oradata/test14.dbf' size 10m, 15 15 '/u01/app/oracle/oradata/test15.dbf' size 10m, 16 16 '/u01/app/oracle/oradata/test16.dbf' size 10m, 17 17 '/u01/app/oracle/oradata/test17.dbf' size 10m, 18 18 '/u01/app/oracle/oradata/test18.dbf' size 10m, 19 19 '/u01/app/oracle/oradata/test19.dbf' size 10m, 20 20 '/u01/app/oracle/oradata/test20.dbf' size 10m; 21 22 Tablespace created.
复制代码

    创建一个包含20个数据文件的表空间,目的是使后面的操作效果比较明显。

1 SQL> create table test (id int) tablespace test; 2 3 Table created.

    向表中插入一些数据,产生一些变化的数据块。

    下面我们来看看数据库进行实例恢复的用时情况。

复制代码
Mon Feb 04 06:38:48 2013 Shutting down instance (abort)
License high water mark = 3 USER (ospid: 3756): terminating the instance
Instance terminated by USER, pid = 3756 Mon Feb 04 06:38:50 2013 Instance shutdown complete
Mon Feb 04 06:39:00 2013 Starting ORACLE instance (normal)
。。。。。。
Mon Feb 04 06:39:11 2013 QMNC started with pid=21, OS id=3938 Completed: ALTER DATABASE OPEN
复制代码

    上面是从alert日志文件中的内容,当我们执行shutdown abort后再启动数据库。从上面可以看出数据库启动的时间是11秒,里面包含实例恢复的时间。
我们将表空间设置为只读。

复制代码
SQL> alter tablespace test read only;

Tablespace altered.

SQL> shutdown abort;
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 330600448 bytes
Fixed Size 1336344 bytes
Variable Size 247466984 bytes Database Buffers 75497472 bytes
Redo Buffers 6299648 bytes Database mounted. Database opened.
----alert日志信息----
Mon Feb 04 06:46:16 2013 Shutting down instance (abort)
License high water mark = 3 USER (ospid: 3934): terminating the instance
Instance terminated by USER, pid = 3934 Mon Feb 04 06:46:17 2013 Instance shutdown complete
Mon Feb 04 06:46:21 2013 Starting ORACLE instance (normal)
。。。。。。
Mon Feb 04 06:46:30 2013 CJQ0 started with pid=21, OS id=4128 Completed: ALTER DATABASE OPEN
 数据库启动的时间为9秒,比上个例子少了2秒。
复制代码

    这个效果不明显,如果在一个大的数据库中,数据文件的个数成百上千,这种差异就会进一步拉大。

实际上,当表空间设置为Read-Only时,数据库启动后,并不会对数据文件进行更新(修改),这在一定程度上缩小了数据库启动的时间。

四、只读表空间可以防止数据被意外删除和修改

    将表空间设置为只读还有一个目的,就是可以防止数据被意外删除和修改。

复制代码
 ----创建一个jack表空间----
 1 SQL> create tablespace jack datafile '/u01/app/oracle/oradata/jack01.dbf' size 500m;  2  3 Tablespace created.  4  5 SQL> show user;  6 USER is "JACK"  ----创建一张表jack----
 7 SQL> create table jack tablespace jack as select * from dba_objects;  8  9 Table created. 10  ----将表空间状态设置为只读----
11 SQL> alter tablespace jack read only; 12 13 Tablespace altered. 14  ----做一些修改数据的操作,无法进行DELETE操作----
15 SQL> delete from jack; 16 delete from jack 17 * 18 ERROR at line 1: 19 ORA-00372: file 6 cannot be modified at this time 20 ORA-01110: data file 6: '/u01/app/oracle/oradata/jack01.dbf' 21  ----无法进行UPDATE操作----
22 SQL> update jack set object_id=object_id*10; 23 update jack set object_id=object_id*10 24 * 25 ERROR at line 1: 26 ORA-00372: file 6 cannot be modified at this time 27 ORA-01110: data file 6: '/u01/app/oracle/oradata/jack01.dbf' 28  ----无法进行INSERT操作,也就是说,对于只读表空间上的数据,无法进行DML操作。----
29 SQL> insert into jack select * from dba_objects; 30 insert into jack select * from dba_objects 31 * 32 ERROR at line 1: 33 ORA-00372: file 6 cannot be modified at this time 34 ORA-01110: data file 6: '/u01/app/oracle/oradata/jack01.dbf' 35  ----也无法进行TRUNCATE操作,说明在只读表空间上,对数据(说的是对象里面的数据)的所有操作都是不允许的,看起来数据还是比较安全的----
36 SQL> truncate table jack; 37 truncate table jack 38 * 39 ERROR at line 1: 40 ORA-00372: file 6 cannot be modified at this time 41 ORA-01110: data file 6: '/u01/app/oracle/oradata/jack01.dbf' 42  ----无法创建对象----
43 SQL> create table echo tablespace jack as select * from dba_objects; 44 create table echo tablespace jack as select * from dba_objects 45 * 46 ERROR at line 1: 47 ORA-01647: tablespace 'JACK' is read-only, cannot allocate space in it 48 49  ----当表空间处于只读的时候,我们可以对表进行其他的修改,给表增加字段----
50 SQL> alter table jack add new_col varchar2(10); 51 52 Table altered. 53 54 SQL> alter table jack modify object_name varchar2(2000); 55 56 Table altered. 57  ----在这里我们可以看到新的字段NEW_COL已经增加,OBJECT_NAME的属性已经修改成VARCHAR2(2000)----
58 SQL> desc jack; 59 Name Null?      Type 60 --------------------- -------- ---------------------------- 61 OWNER VARCHAR2(30) 62 OBJECT_NAME VARCHAR2(2000) 63 SUBOBJECT_NAME VARCHAR2(30) 64 OBJECT_ID NUMBER 65 DATA_OBJECT_ID NUMBER 66 OBJECT_TYPE VARCHAR2(19) 67  CREATED                            DATE 68  LAST_DDL_TIME                      DATE 69 TIMESTAMP VARCHAR2(19) 70 STATUS VARCHAR2(7) 71 TEMPORARY VARCHAR2(1) 72 GENERATED VARCHAR2(1) 73 SECONDARY VARCHAR2(1) 74 NAMESPACE NUMBER 75 EDITION_NAME VARCHAR2(30) 76 NEW_COL VARCHAR2(10) 77  ----无法删除字段----
78 SQL> alter table jack drop column new_col; 79 alter table jack drop column new_col 80 * 81 ERROR at line 1: 82 ORA-12985: tablespace 'JACK' is read only, cannot drop column
复制代码

总结:

凡是要对表空间上的数据进行修改的操作都不允许。比如:

INSERT

UPDATE

DELETE

TRUNCATE

    实际上,只读表空间上的数据块连Oracle都不会修改(SCN号从来都不会改变),这些修改数据的操作自然不被允许的。

    那么,给表增加字段或者修改字段的属性操作为什么就可以呢?

    因为此操作根本就不需要去触碰这个只读表空间,我们只要修改Oracle字典表中的信息就可以了(Oracle的对象属性是存储在数据字典中的,而字典表是存储在SYSTEM表空间上的),因此,这样的操作是被允许的。

    还有,创建对象为什么不可以?它不也是修改数据字典吗?不全是,它同时还需要在表空间上为对象分配空间,这就需要访问表空间,需要修改数据块,所以,不可以。

    同样的,删除一个字段,不仅仅要修改数据字典中表的相关信息,还涉及将该字段上的数据内容从表上抹掉,需要修改表空间上的数据块,因此,不被允许。

这样就清晰了:

    凡是需要修改表空间数据块的操作,都不被允许。

    反之,则可以。

最后,删除这个表以及表上的索引是允许的,因为Oracle只需要从数据字典中将它的所有信息抹去就可以了。

复制代码
 1 SQL> alter tablespace jack read write;  2  3 Tablespace altered.  4  5 SQL> create index jack on jack(object_id);  6  7 Index created.  8  9 SQL> alter tablespace jack read only; 10 11 Tablespace altered. 12 13 SQL> drop index jack; 14 15 Index dropped. 16 17 SQL> drop table jack purge; 18 19 Table dropped.
复制代码
阅读(2397) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~