ITPub博客

首页 > 数据库 > Oracle > Ora Ora Oracle电子杂志:关于剩余数据块的检验 之1-5

Ora Ora Oracle电子杂志:关于剩余数据块的检验 之1-5

原创 Oracle 作者:yaanzy 时间:2005-07-29 16:49:12 0 删除 编辑

订阅Ora Ora Oracle电子杂志已经有几个月了,今天把它的第一个专题《关于剩余数据块的检验》整理了一下

想订阅该杂志的可以访问:http://www.performance-insight.com/china/

[@more@]
<关于剩余数据块的检验 之1>

我们曾经收到这样的问题:
「想知道coalesce(结合)的作用」、「如何确保剩余数据块、作为表的空间使用?」此外,在实际的支持工作中,也经常有客户问到相同的问题。因此,我们将一边检验这些有密切关系的项目,一边向大家说明。

首先向大家说明「coalesce(结合)」。简单的说,就是将空闲空间碎片合并的功能,通常SMON每隔5分钟就会自动执行一次(以前是每隔2小时一次)。要具体说明空闲空间碎片, 例如DROP物理上相邻的10M的表A和20M的表B之后,让空间开放,变成空闲空间。原本相邻的空间中会残存extent边界。

举例来说,在这种情况下,即使想创建25M的表,也会因为空间不足而无法创建。这时候,「coalesce(结合)」的功能就非常重要。简单的说,这项功能的作用就是消除extent边界。这样一来就能确保有30M的空闲空间,可以创建 25M的表C。 (如果空闲空间实际上幷不相邻,那么就算执行「coalesce(结合)」,结果当然也不会改变。要是动态整理空闲空间的配置,处理过程会变得非常沉重。)那么,在什么时间点会进行「coalesce(结合)」呢?

1. 执行alter tablespace <表空间名> coalesce 的时候
2. 每隔5分钟smon会自动执行一次(仅限于设定为表空间pctincrease 0以外的表空间)
3. 不论是否设定为pctincrease 0,假如不执行coalesce,就没有足够的空闲空间分配为extent

现在就让我们来检验各种情况吧。
在1. 的情况下会执行「coalesce(结合)」是很理所当然的,但是我们要看看在Oracle内部究竟发生了什么动作。首先,查查看V$LOCK这个dictionary (在DBA_OBJECTS里V_$LOCK是视图, V$LOCK是其中的SYNONYM)。

*************************************************************
SID  SEQ#  EVENT  P1TEXT  P1
----------------------------------------
5    1457  smon   timer   sleep time 300
*************************************************************

回到原来的主题,运行coalesce的时候为了锁定对象表空间所运行的SQL语句的where语句的t.dflextpct!=0部分,代表pctincrease限定在0以外。另外,where语句的t.bitmapped=0部分是ts# 表的项目,不过其实这和8.1的新功能有关。运行create database的时候,会运行sql.bsq(oracle_home/rdbms/admin)。其中包括了创建这个ts# 表的script。其中, bitmapped带有下面的说明。/* If not bitmapped, 0 else unit size */

通常update的时候, TM和TX是一组,LMODE分别是以3(row exclusive)和6(exclusive)取得。更具体的说,TM的LMODE 3在FET$加上表锁,所以无法从其它程序对FET$进行alter table或drop table。TX的LMODE 6是让rollback segment中正在使用的部分,无法从其它程序使用。

看起来好象是使用bitmap来管理表空间。在USER_TABLESPACES画面,EXTENT_MANAGEMENT项目会根据这个bitmapped以decode函数改换成下面这样。

decode(ts.bitmapped, 0, 'DICTIONARY', 'LOCAL')

如果是0就'DICTIONARY'如果不是就'LOCAL'。

这里表示了表空间的种类不是'DICTIONARY'就是'LOCAL'。'DICTIONARY'是原来的表空间, 'LOCAL'是Local extent management的表空间。换句话说,如果是原来的表空间就还是会coalesce,但是8.1之后的新功能Local extent management的表空间就不会coalesce。

如果是0就'DICTIONARY'如果不是就'LOCAL'。

 

<关于剩余数据块的检验 之2>

~~~~读者的疑问~~~~有位读者问道:coalesce(结合)会自动执行吗?Oracle的版本不同coalesce的动作就会不同吗?只要看了这次的介绍,大家应该就能明白这两个问题的答案。
接着上次的内容,这次要继续介绍剩余数据块的检验。进行“coalesce(结合)”有下面三种时间点:

1. 执行alter tablespace<表空间名> coalesce 的时候
2. 每隔5分钟smon会自动执行一次(仅限于设定为表空间pctincrease 0以外的表空间)
3. 不论是否设定为pctincrease 0,假如不执行coalesce,就没有足够的空闲空间分配为extent

上次我们已经介绍了1.的部分,并且说明了执行1. 的指令之后V$LOCK的动作。
这次我们将检验2.的部分并且加以说明。 首先,我们先单纯地确认pctincrease取值为0和非0的时候,间隔了5分钟之后会不会执行coalesce。当然,在进行检验之前,先执行CREATE TABLEDROP TABLE等步骤,创建有extent边界的剩余数据块。换句话说,先让系统生成碎片。结果,在pctincrease0的情况下,不会执行coalesce,但是在pctincrease0的情况下会执行coalescecreate tablespacealter tablespacedefault storage指定的pctincrease有两种意义。一种是现在检验的“是否执行coalesce”,另一种是执行create table的时候, 如果没有指定pctincrease,就会以缺省设定使用存放那个表的tablespacepctincrease
此外,coalesce是以表空间为单位,所以即使对一些TABLE指定了几个pctincrease,对表空间来说,是以pctincrease是不是0决定。接下来,我们来看看smon执行coalesce的时候为了锁定对象表空间所执行的SQL语句。下面是在Oracle 8.1的环境得到的结果。

 
*************************************************************
select f.file#, f.block#, f.ts#, f.length from fet$ f, ts$ t 
where t.ts#=f.ts# and t.dflextpct!=0 and t.bitmapped=0
*************************************************************

顺带一提,这个sql语句可以利用

 
*************************************************************
SELECT SID,SQL_TEXT FROM V$SQL ,V$SESSION 
WHERE ADDRESS = SQL_ADDRESS AND TYPE='BACKGROUND';
*************************************************************


在BACKGROUND执行就能看得到sql语句,请大家试试看。另外,看看v$session_wait,就能看到每隔300秒,也就是每隔5分钟,smon就会执行一次。

下面的SID(Session ID)和上面在BACKGROUND执行的SQL语句的SID一致。

 
*************************************************************
SID  SEQ#  EVENT  P1TEXT  P1
----------------------------------------
5    1457  smon   timer   sleep time 300
*************************************************************


回到原来的主题,执行coalesce的时候为了锁定对象表空间所执行的SQL语句的where语句的t.dflextpct!=0部分,代表pctincrease限定在0以外。另外,where语句的t.bitmapped=0部分是ts# 表的项目,不过其实这和8.1的新功能有关。 执行create database的时候,会执行sql.bsq(oracle_home/rdbms/admin)。其中包括了建立这个ts# 表的script。其中, bitmapped带有下面的说明。/* If not bitmapped, 0 else unit size */

看起来好像是使用bitmap来管理表空间。在USER_TABLESPACES画面,EXTENT_MANAGEMENT项目会根据这个bitmapped以decode函数改换成下面这样。

decode(ts.bitmapped, 0, 'DICTIONARY', 'LOCAL')

如果是0就返回'DICTIONARY'如果不是就返回'LOCAL'。

这里表示了表空间的种类不是'DICTIONARY'就是'LOCAL'。'DICTIONARY'是原来的表空间, 'LOCAL'是Local extent management的表空间。换句话说,如果是原来的表空间就还是会coalesce,但是Oracle 8.1之后的新功能Local extent management的表空间就不会coalesce。

因为Local extent management是Oracle 8.1之后的新功能,所以更早的版本的SQL语句的where语句只到where t.ts#=f.ts# and t.dflextpct!=0为止。

关于Local extent management,过一阵子我们会另外加以检验说明。在Oracle 8.1当中,会在create tablespace的时候决定究竟是Local extent management还是原来的表空间。Oracle 8.1的sql说明手册的create tablespace语句和Oracle 8.1的概要里有详细说明,请大家参考。

大家明白coalesce了吗?此外,关于SMON的自动coalesce功能,根据我们检验的结果,Oracle7.1.6之后的版本都会执行。
(之前的版本我们没有进行检验)

读者问题

这是我们接到的问题:“系统运行稳定而且会自动备份,我现在身为系统管理者,该如何管理系统呢?”
☆★回答★☆
系统运用管理的目的当然是要保证系统运行稳定,“运行稳定”的意思当然包括不让系统的服务停止,而且要防止系统响应速度低,以及各种性能要素的管理。要让系统稳定运作,有下面两项重点: 1. 能够防范的问题就要事先防范 2. 如果还是发生问题就要迅速处理、恢复系统。

1.
防范问题发生
首先必须管理的是系统空间,不论是运行的多么稳定的系统,系统数据一定会持续增加。这时候可能会因为空间(硬盘空间容量)问题造成insert数据失败,例如下面几种情况:
a)
已经达到表的max extent,导致extent扩展失败
b)
虽然事先把表的max extent设为unlimited避免发生a) 的情况,但是因为表空间用尽,导致extent扩展失败
c)
虽然事先指定表空间为autoextend避免发生b) 的情况,但是硬盘空间不足,导致数据档案扩展失败
系统出现这些错误的时候,会生成Alert日志档案,所以Alert日志是很重要的监视项目。此外,Alert日志档案里还会留下alter tablespace之类的数据库结构修改记录。
空间管理不仅在数据库中需要,在OS上也同样需要。刚才说的Alert日志档案的输出磁盘当然空间有限,所以需要作空间管理,归档(archive)日志的输出装置空间管理也是非常重要的监视项目。
大家看了上面的说明应该已经了解,要管理系统,是不可能逃避空间管理的工作的。此外,从系统性能的角度来看,执行updatedeleteinsert之后会导致B-tree索引的构造歪曲。要是歪曲情况严重,会导致系统的物理读取量增加,结果使用那个索引的SQL语句的性能会恶化。
除了监视之外,还要定期重新建立(drop & createrebuild)索引。
数据量增加,或者B-tree结构歪曲的时候,就会导致物理读取量增加,当然就会使得读进内存的数据量增加。因此,除了管理系统空间之外,还得监视内存。具体来说,从磁盘进行物理读取的时候,必须监视latch(记忆体上像锁一样的东西)互相冲突的比率高不高。

2.
发生问题就要迅速处理、恢复系统
即使用尽办法防范问题,问题总是难免会发生。(例如产品本身的问题或硬件故障)所以,事先就准备好随时可以处理、恢复系统是很重要的,务必让损害减到最小。随时准备好及早察觉问题,避免其他问题接连发生。即使是需要恢复数据库的最糟的情况下,也需要按照正确步骤快速完成恢复数据库的工作。
为了发生问题时可以迅速处理、恢复系统,平时必须备份。发问的读者平时不知道是用export的方法还是用OS指令备份数据档案,不过,建议大家最好亲自演练还原(restore)操作。很多客户都说,就算平时有备份也没有明确的工作流程说明书,即使有说明书可能也有错,即使说明书没有错但是因为是别人写的,自己亲自做的时候才发现还是不懂。 而且有时候会因为介质故障结果数据无法复原,或者遗漏重要档案的备份,都是可能发生的问题。
漏掉了必要的备份档案时,如果是因为用来备份的表空间不足,可能会用alter tablespace追加数据档案。其实这时候追加的数据档案也要备份,但是很多人都忘了追加补钉程序。身为管理者,最好还是定期演练恢复数据库的步骤,备份的对象改变(增加)的时候就要立刻调整,以防日后发生问题时手忙脚乱。再怎么稳定的系统也需要监视,越了解数据库,就越觉得监视很重要。
本公司的Performance Insight是常驻在数据库的监视工具,可以制作从各种角度诊断系统的评价报告书,以mail通知系统管理者上面介绍的管理项目以及其他大约400种提示。如果大家希望平时的管理工作更轻松,请务必试用一次,体会轻松监视管理的好处。

<关于剩余数据块的检验 之3>

~~~~读者的疑问~~~~
有位读者问道:coalesce(结合)会自动执行吗?Oracle的版本不同coalesce的动作就会不同吗?只要看了这次的介绍,大家应该就能明白这两个问题的答案。

接着上次的内容,这次要继续介绍剩余数据块的检验。
进行“coalesce(结合)”有下面三种时间点:

1. 执行alter tablespace<表空间名>coalesce 的时候
2. 每隔5分钟smon会自动执行一次(仅限于设定为表空间pctincrease 0以外的表空间)
3. 不论是否设定为pctincrease 0,假如不执行coalesce,就没有足够的空闲空间分配为extent

目前为止已经说明了1.和2.,这次我们要检验并说明3.的情况。为了检验第三种情况,要事先准备10个剩余数据块,每个剩余资料块包含20个相连数据块。这是因为我希望各位读者想像每20个数据块就有一个extent边界。

此外,coalesce是以表空间为单位,所以即使在某些TABLE中指定了一些pctincrease值,对表空间来说,还是由pctincrease是不是0决定是否进行coalesce。接下来,我们来看看smon执行coalesce的时候为了锁定对象表空间所执行的SQL语句。下面是在Oracle 8.1的环境得到的结果。

下面是检查剩余数据块状况的SQL语句及其执行的结果。检查剩余数据块的情况时,我们使用DBA_FREE_SPACE视图。

*************************************************************
SELECT TABLESPACE_NAME,BLOCK_ID,BYTES,BLOCKS 
>FROM DBA_FREE_SPACE WHERE TABLESPACE_NAME='CRE20'
ORDER BY BLOCK_ID;

TABLESPACE_NAME  BLOCK_ID  BYTES  BLOCKS
----------------------------------------
CRE20            2         40960  20
CRE20            22        40960  20
CRE20            42        40960  20
CRE20            62        40960  20
CRE20            82        40960  20
CRE20            102       40960  20
CRE20            122       40960  20
CRE20            142       40960  20
CRE20            162       40960  20
CRE20            182       40960  20
*************************************************************

要判断数据块是否连续,只要看BLOCK_ID+BLOCKS是不是下一行的BLOCK_ID就行了。(例如:第1行的BLOCK_ID=2 + BLOCKS=20等于下一行的BLOCK_ID=22)在这种状态下执行create table建立30个initial数据块,剩余数据块的状态如下。 (如果db_block_size=2k就指定INITIAL 60k)

*************************************************************
TABLESPACE_NAME  BLOCK_ID  BYTES  BLOCKS
----------------------------------------
CRE20            2         40960  20
CRE20            52        20480  10 (確定BLOCK_ID 22~51是INITIAL)
CRE20            62        40960  20
CRE20            82        40960  20
CRE20            102       40960  20
CRE20            122       40960  20
CRE20            142       40960  20
CRE20            162       40960  20
CRE20            182       40960  20
*************************************************************

含有BLOCK_ID 22到51这30个数据块的表被建立,所以剩余数据块在物理上被切断了。不论再怎么结合,实际上不相邻的剩余数据块永远不会合并在一起。

通常每隔5分钟smon就会自动执行的结合动作一下子就结束了, 但是我曾经看过有的site会持续不断的执行结合动作。那是正在进行大型的表的truncate处理或drop table处理步骤很多的site。持续不断进行结合,每个instance中唯一的ST enqueue会不停重复等待状态。在这种site,就在表空间指定pctincrease为0,不要让smon执行结合,可以减轻系统的负荷。因为Oracle数据库内部有一项功能,不管有没有设定pctincrease为0,都会在必要的时候将内部相邻的extent互相结合。
读者问题1
如果表的PCTINCREASE变化,会让空间管理变得困难或变得简单吗?

《回答》

(下面的回答是针对指定在表的pctincrease设定,不是执行结合时相关表空间的pctincrease设定。)

1. 防范问题发生
让表的PCTINCREASE变化,例如指定pctincrease=50,可以分成两方面来说。首先,extent呈现指数倍数型扩张,会导致表空间很难管理。此外,表空间的剩余空间容易发生碎片化(无法再利用的部分会增加)。要考虑空间管理,所以前提是不能只考虑一个表,必须以表空间为单位考虑。

《extent呈现指数倍数型扩张》
一般而言,无法预计日后会增加的数据量的时候,就把表的pctincrease设为50。相反地,可以估计(数据量增长微少)的时候,也可以把pctincrease设为0。例如存放销售业绩的事务表通常是无法预计的情况。

下面就实际指定pctincrease=50,看看建立表的时候空间的分配情況。

db_block_size=2k的环境下

*************************************************************
create table cre1 (col1 number)
storage(initial 100k next 100k pctincrease 50 minextents 10);
*************************************************************

参照dba_extents

*************************************************************
SEGMENT_NAME  EXTENT_ID  BLOCKS
--------------------------------------------------------------
CRE1          0          50    
CRE1          1	         50    
CRE1          2	         75    
CRE1          3	         115   
CRE1          4	         170   
CRE1          5	         255   
CRE1          6	         385   
CRE1          7	         575   
CRE1          8	         865   
CRE1          9	         1295  
*************************************************************


下面分配extent的计算,只做1.5的乘法,结果就不一样。这里用到的计算方法会在以后的“关于剩余数据块的检验 之5”有详细说明,这次先请大家注意,刚开始分配50个数据块的表在第10次的extent分配会涵盖1295个数据块。但是,假如无法预测数据量,总是分配50个数据块的话,马上就会达到maxextents。

ORACLE7.3之后的版本可以把maxextents设为unlimited,但是,如果有很多extent就会导致性能恶化。这时候最好把pctincrease设为50,只不过空间管理还是很难。因为这是无法预测数据量而产生的问题,所以无法避免。最理想的情况是initial就能处理所有资料,可惜通常情况不会这么顺利。

《表空间的剩余空间碎片化问题》

如果pctincrease=0,频繁地执行DROP TABLE、CREATE TABLE、TRUNCATE TABLE时,表空间上的空间可以有效的再利用。这是因为pctincrease为0的话,NEXT会保持固定,extent分配和释放的大小会相同。但是因为这是以表为单位,所以和其他表的NEXT不同的时候,表空间整体的效率未必高。还有其他表的时候,就空间管理的角度来看,extent的大小最好是和表空间中所有表的INTIAL、NEXT相同或是成倍数,碎片化的情况会比较少。只把pctincrease设为0,未必可以有效的管理数据库空间。

还有另一个空间管理的解决方法,在ORACLE8之后可以在表空间指定minimum extent。我们会在下次的内容为大家介绍。

读者问题2
想提高Oracle的性能,该如何处理RAID5的结构?比较重视查询的时候的回应速度,不重视Insert和Update时的性能。

《回答》

如果不重视Insert和Update时的性能,那么把Oracle的DATAFILE和CONTROLFILE放在RAID5上也没关系。(如果写入的性能很重要,就建议大家不要放在RAID5。)但是千万不要把“重做日志文件(REDO log file)”放在RAID5。重做日志文件是“连续写入(sequentialwrtie)”,如果“磁盘只用在REDO log file”,就能消除磁盘的“搜寻延迟时间(seek overhead)”。因此,请把重做日志文件放在独立的磁盘。

<关于剩余数据块的检验 之4>

这次要从表的角度检验剩余数据块的空间分配方式,我会按照下面的顺序说明。

接着上次的内容,这次要继续介绍剩余数据块的检验。有如下三个知识点:

1. 关于minimum extent
2. 尽量不要留下剩余空间碎片的方式﹝以后再说明﹞
3. 表示剩余数据块如何被使用的流程图﹝以后再说明﹞

先向大家说明1.的部分。简单说来minimum extent指定空间管理单位的byte数,实际上是以数据块为计算单位。从Oracle 8.0版本之后就有这个功能。

(1) 先看具体的例子:
下面的情况是执行create tablespace,指定byte单位为80k。因为db_block_size=2k,所以是指定了80K/2K=40个数据块(单位)进行空间管理。

*************************************************************
create tablespace test datafile
'/shome/share/koba/oradata/test.ora' SIZE 880k
minimum extent 80k
default storage (pctincrease 0);
*************************************************************

(2)在这个表空间上建立表的CHAMU。
*************************************************************
CREATE TABLE CHAMU (COL1 NUMBER) TABLESPACE TEST 
STORAGE (INITIAL 2K NEXT 2K PCTINCREASE 0 MINEXTENTS 5);
*************************************************************

这是1个数据块建立5个extent的命令,结果会如何?

让我们看看DBA_EXTENTS。
*************************************************************
SEGMENT_NAME  TABLESPACE_NAME  EXTENT_ID  BLOCK_ID  BYTES  BLOCKS
-----------------------------------------------------------------
CHAMU         TEST             4          2         81920  40
CHAMU         TEST             2          42        81920  40
CHAMU         TEST             0          82        81920  40
CHAMU         TEST             1          122       81920  40
CHAMU         TEST             3          162       81920  40
*************************************************************

虽然指定了2KB的extent(1数据块),可是extent还是以40个数据块为单位。可见这是以在minimum extent指定的40个数据块为单位分配空间。

(3)从DBA_FREE_SPACE看看表空间的剩余数据块。
*************************************************************
TABLESPACE_NAME  BLOCK_ID  BYTES   BLOCKS
-----------------------------------------
TEST             202       489472  239
*************************************************************

可以看出239个数据块空闲,可是这比40个数据块*6还少。换句话说,顶多只剩下5个extent。假如不改变MINIMUM EXTENT,就会有39个数据块变成完全未使用的空间。

(4)以CREATE TABLESPAC指定数据档案的大小为880K之后,剩余数据块的情况如下。
*************************************************************
TABLESPACE_NAME  BLOCK_ID  BYTES   BLOCKS
-----------------------------------------
TEST             2         899072  439
*************************************************************

(880K/2K)─(标题1个数据块) = 439个数据块。数据文件的标题使用1个数据块,所以如果minimum extent是80k,考虑标题部分,最好指定数据文件的大小是882k才不会造成空间浪费。

ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME FILE_HDRS LEVEL 10';

跟踪文件(trace file)会输出到初始参数的user_dump_dest。

再从空间管理的好处考虑minimum extent。举例来说,要把表放到minimum extent指定为100k的表空间时,如果频繁地执行DROP TABLE、CREATE TABLE、TRUNCATE TABLE等等,因为空间管理单位已经固定了,因此可以很有效率地进行空间的释放和取得。即使发生碎片化的情况,也是以100K为单位,是可以再利用的范围。上一周的“问题1”已经谈过这个问题,请回头参考这部分的内容。

决定minimum extent的大小的指标是释放空间的对象。在日常业务处理时会需要释放空间的包括下面几项:
※为了某个处理在过程中建立的表
※经常执行REBUILD或DROP AND CREATE的索引的表领域
※以日期搜索partition表并DROP旧日期数据

注意这些对象的大小,掌握释放空间的单位,决定minimum extent。还有,执行DELELE的时候不会释放空间。

 

读者问题1
coalesce是从Oralce7就有的吗?现在公司使用的环境是Oracle7.3但说明书是7.2,在说明书的ALTER TABLESPACE没有提到那个参数。

《回答》
ALTER TABLESPACE COALESCE; 是从Oracle7.3才有的功能,以前的版本虽然SMON也会每隔5分钟执行一次结合,但是没有提供这个命令。顺带提一下,SMON不把PCTINCREASE为0的表空间视为结合对象,好像是从7.1.x开始。到7.0为止,不论PCTINCREASE是多少,所有的表空间都会是结合的对象。

读者问题2
SELECT TABLESPACE_NAME,BLOCK_ID,BYTES,BLOCKS FROM DBA_FREE_SPACE ORDER BY BLOCK_ID;
执行这个命令之后,ROLLBACK_DATA的数据块ID重复,有5行内容相同,这是因为回滚段的剩余数据块比较特殊吗?

《回答》
这应该是因为表空间由5个数据文件组成,不是因为回滚段的剩余数据块比较特殊。请试试看下面的SQL语句,即使在数据文件分成几个的情况下也适用。
SELECT TABLESPACE_NAME,file_id,BLOCK_ID,BYTES,BLOCKS FROM DBA_FREE_SPACE where TABLESPACE_NAME=' ' ORDER by file_ID, BLOCK_ID;

读者问题3
如果对1个表执行很多次analyze命令,会不会导致响应速度降低?我发现自己调优系统的时候,执行1次之后看起来改善了,再执行一次analyze之后响应速度就变慢了。不管我是否修改表,情况都一样。我试过把初始参数文件的OPTIMIZER_MODE设定成预设、ALL_ROWS、FIRST_ROWS,可是变慢的情况没有改变。

《回答》
通常执行几次analyze会导致回应速度减低,一定是因为TABLE里的数据改变。回应速度变慢的根本原因在于执行计划改变,最好查出有问题的SQL语句,调查执行计划。

 

<关于剩余数据块的检验 之5>

这次要从表的角度检验剩余数据块的空间分配方式,我会按照下面的顺序说明。

接着上次的内容,这次要继续介绍剩余数据块的检验。有如下三个知识点:

1. 关于minimum extent
2. 尽量不要留下剩余空间碎片的方式﹝以后再说明﹞
3. 表示剩余数据块如何被使用的流程图﹝以后再说明﹞

这次要继续介绍1.的部分,如果在create tablespace时没有指定minimum extent的话, default会是0。我们一起看看这时候系统的动作。

在db_block_size=2k的数据库环境里,不指定minimum extent,建立表空间TEST,以INITIAL 2K(1个资料块)在表空间里建立表dummy1,执行下面的100个alter table语句。这是以指定的大小分配extent的命令。

*************************************************************
alter table dummy1 allocate extent (size 2k); 1 extent block 
alter table dummy1 allocate extent (size 4k); 2 extent block
alter table dummy1 allocate extent (size 6k); 3 extent block
..............................................
alter table dummy1 allocate extent (size 196k); 98 extent block
alter table dummy1 allocate extent (size 198k); 99 extent block
alter table dummy1 allocate extent (size 200k); 100 extent block
*************************************************************

检索dba_extents视图会出现什么结果?
*************************************************************
SEGMENT_NAME  EXTENT_ID  BLOCK_ID  BLOCKS
-----------------------------------------
DUMMY1        0          2         2     ←initial extent
DUMMY1        1          4         1     ←next 1 block
DUMMY1        2          5         2     ←next 2 block
DUMMY1        3          7         3     ←next 3 block
DUMMY1        4          10        4     ←next 4 block
DUMMY1        5          14        5     ←next 5 block
DUMMY1        6          19        10    ←next 6 block﹝理论上应该是这样﹞
DUMMY1        7          29        10
DUMMY1        8          39        10
DUMMY1        9          49        10
DUMMY1        10         59        10
..........................................
DUMMY1        91         4269      95
DUMMY1        92         4364      95
DUMMY1        93         4459      95
DUMMY1        94         4554      95
DUMMY1        95         4649      95
DUMMY1        96         4744      100
DUMMY1        97         4844      100
DUMMY1        98         4944      100   ←next 98 block﹝理论上应该是这样﹞
DUMMY1        99         5044      100   ←next 99 block﹝理论上应该是这样﹞
DUMMY1        100        5144      100   ←next 100 block
*************************************************************

先注意initial应该是2k(1个数据块),可是却变成2个数据块。这是因为段标题空间,在表里面占用1个数据块。所有的表一定有一个数据块是段标题,所以initial一定要是2个数据块以上。另外请大家确认,下一个next确实分配了1个数据块,而且只分配了一个数据块。

接下来,请注意分配了6 block extent的地方,实际上分配了10个数据块,而且之后是以5个数据块为单位无条件进位。1~5block是根据指定的大小分配extent,从第6个才开始以5个数据块为单位无条件进位。

不仅在上面的alter table的allocate extent是这样,insert之后的结果extent已经满了,要分配下一个extent的时候(数据增加而形成extent),也会发生和这次同样的分配情况。

另外,指定了pctincrease还是会以5个数据块为单位进位。只是要注意计算pctincrease的尾数进位和以5为单位的进位顺序。(在“关于剩余数据块的检验 之2”的问题专区也有相关介绍。)
*************************************************************
db_block_size=2k的环境

-----------------------------------------------------------------
create table cre1 (col1 number)
storage(initial 100k next 100k pctincrease 50 minextents 10);
*************************************************************

参照dba_extents
*************************************************************
SEGMENT_NAME  EXTENT_ID  BLOCKS
-------------------------------
CRE1          0          50    intial
CRE1          1          50    next
CRE1          2          75    50 *1.5=  75.0  以5个数据块为单位进位
CRE1          3          115   75 *1.5= 112.5  以5个数据块为单位进位
CRE1          4          170   113*1.5= 169.5  以5个数据块为单位进位
CRE1          5          255   170*1.5= 255.0  以5个数据块为单位进位位
CRE1          6          385   255*1.5= 382.5  以5个数据块为单位进位
CRE1          7          575   383*1.5= 574.5  以5个数据块为单位进位
CRE1          8          865   575*1.5= 862.5  以5个数据块为单位进位
CRE1          9          1295  863*1.5=1294.5  以5个数据块为单位进位
*************************************************************

 

读者问题1
ORACLE是7.3和8.0,OS是NT,使用者有UNLIMITED TABLESPACE系统权限。以USER_TS_QUOTAS看到下面的结果。
*************************************************************
 TABLESPACE_NAME  BYTES      MAX_BYTES BLOCKS  MAX_BLOCKS
 -----------------------------------------------------
 USR              265011200  0         129400  0
*************************************************************

据我所知,1)UNLIMITED TABLESPACE系统权限的使用者不会受限于CREATE USER时的设定,所有的表空间都可以分配无限制的QUOTA。 2)以USER_TS_QUOTAS看到BYTES、BLOCKS 不但>0而且MAX_BYTES、MAX_BLOCKS =0,代表那个使用者在那个表空间建立表之后,QUOTA修改为0,已经存在的对象会继续存在,也可以更新。已经分配完的extent里如果还有空闲空间,还可以INSERT。可是,如果更新需要扩张新的extent,就不可以更新。我觉得1)和2)好像互相矛盾,是不是我的认识有错误呢?

《回答》

1)和2)都没有错,只是需要补充另一点。如果有UNLIMITED TABLESPACE系统权限,在CREATE USER时以QUOTA语句明确指定的表空间使用限制,会被改为UNLIMITED。如果以REVOKE取消UNLIMITED TABLESPACE系统权限,在CREATE USER时以QUOTA语句明确指定的表空间使用限制就会再次恢复。这就像是SELECT ANY TABLE权限与明确指定的SELECT对象权限。但是,即使设定了UNLIMITED TABLESPACE系统权限,从DBA_TS_QUOTAS也看不到。只能确认CREATE USER和ALTER USER的时候指定的QUOTA语句。

UNLIMITED TABLESPACE权限与其他的系统权限稍微不同。UNLIMITED TABLESPACE权限通常是从事先定义过的角色的RESOURCE和DBA赋予使用者权限。

请看下面,不可思议的是从dba_sys_privs看RESOURCE 角色的系统权限,也没有UNLIMITED TABLESPACE权限。(dba_sys_privs的GRANTEE(权限接收者)会表示角色和使用者)
*************************************************************
select * from dba_sys_privs where grantee = 'RESOURCE';

GRANTEE                        PRIVILEGE                                
------------------------------ ---------------------------------------- 
RESOURCE                       CREATE CLUSTER                           
RESOURCE                       CREATE INDEXTYPE                         
RESOURCE                       CREATE OPERATOR                          
RESOURCE                       CREATE PROCEDURE                         
RESOURCE                       CREATE SEQUENCE                          
RESOURCE                       CREATE TABLE                             
RESOURCE                       CREATE TRIGGER                           
RESOURCE                       CREATE TYPE                              
*************************************************************

再看下面,赋予RESOURCE和DBA 角色的使用者OSAMU具有UNLIMITED TABLESPACE权限。像这样赋予RESOURCE和DBA 角色之后,会执行对使用者明确赋予权限的动作。
*************************************************************
select * from dba_sys_privs where grantee = 'OSAMU';

GRANTEE                        PRIVILEGE                                
------------------------------ ---------------------------------------- 
OSAMU                          UNLIMITED TABLESPACE                     
*************************************************************

如果赋予角色UNLIMITED TABLESPACE权限,情况会如何?像下面这样,无法给角色UNLIMITED TABLESPACE权限,但是可以指定给使用者。
*************************************************************
GRANT UNLIMITED TABLESPACE TO ROLEMAN;

ORA-01931: cannot grant UNLIMITED TABLESPACE to a role
*************************************************************

因此,要看是否有UNLIMITED TABLESPACE权限,请在dba_sys_privs注意看GRANTEE的使用者名。

读者问题2
如果coalesce就能取得空闲空间,在PCT_INCREASE为0且设定了AUTO EXTEND的表空间建立extent时,应该以coalesce还是AUTO EXTEND为优先?

《回答》
以coalesce优先,如果结合之后还是没有足够的空闲空间,才考虑使用AUTO EXTEND。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/3898/viewspace-803450/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    108
  • 访问量
    761519