Oracle内核技术揭密_吕海波 学习笔记
常说一个表就是一个段,但表和段是两个不同的概念,表是逻辑概念,比如表有几列,列的类型、长度,这些信息都属于表;段是物理概念,它只代表存储空间,区就属于段,一个段至少包含一个区。
oracle中每个对象都有一个ID,在DBA_OBJECTS视图中,object_id列是表ID,data_object_id列是段ID:
SQL> select object_id,data_object_id from dba_objects where owner='MA' and object_name='T62';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
93456 93456
SQL> truncate table ma.t62;
SQL> insert into ma.t62 values(1,'a1');
SQL> commit;
SQL> select object_id,data_object_id from dba_objects where owner='MA' and object_name='T62';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
93456 93588
从上面的代码可知,刚开始表ma.t62的表ID和段ID都是93456,当truncate表后重新插入数据,表ID没变,段ID变为93588了。这是因为表ID创建后就不会再变,当truncate后,oracle会删除原来的段,再插入数据时会重新分配新的区,表就有了新的段,也就有了新的段ID。
块中空间的使用
常见的数据块大小为8K,它包含两部分信息:管理信息和用户数据。管理信息包括块头的SCN和ITL槽等。
当删除一行数据,再回滚,这行数据的物理位置是没有变的。当删除一行提交后,只是在这一行上做了一个删除标记,声明此行所占的空间可以被覆盖。当删除未提交时,事务加在行上的锁未释放,虽然做了删除标记,但仍不能被覆盖。删除行再回滚,由于原数据空间没有被其它数据覆盖,此时回滚段里的前镜像重新插入数据到原位置,不需要另外寻址。如果是删除提交后再插入,就需要重新寻址了,数据的物理位置就会发生变化。(PS:不明的为什么不是直接取消删除标记来达到回滚效果;难道与SCN号的变化有关?被删掉那笔数据的SCN号不可用?)
SQL> select dbms_rowid.rowid_relative_fno(rowid) fno,
dbms_rowid.rowid_block_number(rowid) block_id,
DBMS_ROWID.ROWID_ROW_NUMBER(rowid) row_id,
id
from ma.t62;
FNO BLOCK_ID ROW_ID ID
---------- ---------- ---------- ----------
8 133 0 1
8 133 1 2
8 133 2 3
8 133 3 4
SQL> delete from ma.t62 where id=2;
SQL> select dbms_rowid.rowid_relative_fno(rowid) fno,
dbms_rowid.rowid_block_number(rowid) block_id,
DBMS_ROWID.ROWID_ROW_NUMBER(rowid) row_id,
id
from ma.t62; 2 3 4 5
FNO BLOCK_ID ROW_ID ID
---------- ---------- ---------- ----------
8 133 0 1
8 133 2 3
8 133 3 4
SQL> rollback;
SQL> select dbms_rowid.rowid_relative_fno(rowid) fno,
dbms_rowid.rowid_block_number(rowid) block_id,
DBMS_ROWID.ROWID_ROW_NUMBER(rowid) row_id,
id
from ma.t62; 2 3 4 5
FNO BLOCK_ID ROW_ID ID
---------- ---------- ---------- ----------
8 133 0 1
8 133 1 2
8 133 2 3
8 133 3 4
oracle在插入行时,会在数据块中设一个标记位,记录空间使用到哪儿了。块中用户数据所占空间是从下往上分配的,假设往一个8192字节的块中插入5行,每行100字节,插入后标记位指到(8192-500)7692字节处。如果删除一行并提交,标记位的值不会变,当插入新行时,将会从7692处向上查找可用空间,删除行释放的空间不会被使用。当标记位值越来越小,向上达到管理信息的边界时,标记位会再变为8192。这也说明了删除提交后,再插入数据时位置发生变化的原因了。