1、数据库的结构:
1、控制文件(ctl):其中有四类信息,分别是
数据库的物理结构信息,
数据库的归档历史信息,
各个数据文件的scn号和check point(系统检查点)
rman源数据。这四类信息很重要,接下来可以仔细研究一下:
2、redo log files:redo日志文件有多组,每组内都有多个成员。成员之间是完全相同的关系,一般分为group1,group2,group3。。。等组。这样就可以实现多组复用。redo log 有四种状态,分别是 unused,inactived,active,courent。当处于courent状态的时候如果redo log 丢失,就会丢失数据,且听我慢慢分析,我们知道实例恢复其实就是根据redo log重新构造脏块,然后有dbwr进程将数据写入磁盘的过程。回头再看由于数据库提交事务日志和数据写入磁盘的不一致性,导致了redo log记录事务已经提交,但是实际上数据还在脏块里的事情是有的,如果此时丢失,就发生了无法恢复的数据丢失。
orcole在redo log 中记录每一个 数据块的修改的版本号,在数据恢复的时候,如果发现日志的版本号比数据块的版本号要低,那日志就空跑。。当检查点进程(CKPT进程)触发时候 会在当前的缓冲区内找到一个叫检查点队列的列表,然后找到里面 最早脏数据块的地址 写入控制文件,这样下次启动的时候,oracle就知道了从哪个日志开始恢复脏块。
3、数据文件(dbf):
oracle创建一个表的时候,先做两件事,先去oracle数据字典中把该表的信息写入,如表名,有多少列,列的名字属性等信息。第二件事,在表空间内分配空间。。
但是创建一个视图的时候,oracle只做一件事,那就是把视图的信息写到数据字典里。
2、database interface:
就是一些em,gc,sqlplus之类的与oracle数据库进行交互的工具。
desc命令一般是用来描述一个表的,但是一般人不知道他用来描述一个包是很有用的。
3、select *:
相老师说select * 会严重降低查询的性能,他说这与数据行在数据块中的存储是相关的,我研究了一下这些数据行在块中是如何存储的,现在整理如下:
数据行是由n(n是一个或者多个)个行片段来存储的,但是有一点,这些行片段只能存储数据表的前255列。
接下来看第一种情况:一个块可以纳一个完整的数据行,且这个数据行小于255列,则这个行用一个行片段来存储。当新插入或者更新数据行,导致一个块不能容纳这个数据行的时候,这时oracle会用另个一个数据块的行片段来存储这一行。这一行也就成了多个数据块之间的行链接。
接下来看第二种情况:一个块可以容纳一个完整的数据行,但是这个表的列大于255列,假设900列吧,但是列的数据还是比较小,整个行都可以存在同一个数据块里,这时,oracle会在同一个块里分好几个行片段来存储,每个行片段存储255列。这就构成了块内链接。这时在块内用各行片段的rowid进行行内链接,这样同一个块内不会产生I/O。
每一个行片段都有两大部分组成:行头 和 列数据。(可以想象的到,如果某列的数据非常大,可能跨多个行片段,也可能跨多个数据块哈哈)
行头:包含以下内容:行管理开销、列数、簇键ID(如果是簇表)、行片段链接的rowid(如果有行链接)。
列数据:各列的列长及列内容。
如果一行能被存储于一个数据块中,那么其行头所需容量将不少于3 字节。在行头信息之后依次储存的是各列的列长及列值。列长存储于列值之前,如列值不超过250 字节,那么 Oracle 使用1 字节存储其列长;如列值超过250 字节,则使用3 字节存储其列长。列数据所需的存储空间取决于此列的数据类型。如果某列的数据类型为变长的,那么存储此列值所需的空间可能会随着数据更新而增长或缩小。
为了节约存储空间,如果某列值为空,那么数据库中只存储其列长(值为 0),而不存储任何数据。对位于一行末尾的空列值,数据库中将列长也忽略不予存储。另外,每行还要占用数据块头中行目录区的2 字节空间。簇表内的行需要存储与非簇表行相同的信息。除此之外,簇表内各行还需要存储其所属的簇键。
行片段的 rowid
Oracle 使用 rowid 记录每个行片段的存储位置和地址。每个行片段得到一个 rowid 之后,这个值将会保持不变,直到其所属行被删除或经过 Oracle 工具导出并再次导入。对于簇表来说,如果某行的簇键值发生改变,那么此行除了保存原有的 rowid 之外,还将为新簇键值存储一个额外的 rowid 指针。由于行片段在其生命周期内拥有固定的 rowid,因此在 SELECT,UPDATE,及 DELETE 等 SQL 语句中可以充分利用 rowid 的这个特性。
4、数据库启动的三个阶段:
这三个阶段分别是 startup nomount、mount、open 。
第一步:startup nomount:oracle根据当前的oracle_sid到 dbs目录下的spfileorcl.ora文件,根据文件的参数设置,初始化一块内存区域,分配各个SGA组件,同时启动相应的后台进程。好了,这个实例产生了。(如果这个时候数据库启动不了,报出spfile错误等,那就说明只有一个原因,spfileorcl.ora文件除了问题。)
第二步:mount:即为打开控制文件的过程,再根据spfileorcl.ora文件找到控制文件的位置,将控制文件打开。(如果数据库不能mount 了,那一定是控制文件出问题了)
第三步:open:这个过程就是打开 redo log 和 dbf文件的过程。但是这个时候你的知道数据库的物理结构,在哪知道呢?第二步的mount时,就已经找到了控制文件,控制文件中就记录了数据库的物理结构。
在打开数据文件的后,肯定要判断这个数据库是需要实例恢复呢?还是需要介质恢复呢?怎么判断呢?这里先不细说了,只要知道主要是通过SCN号来判断的,控制文件里有scn号,数据文件里头部也有SCN号,还有redo log 的SCN号。。。在数据文件的头部,除了scn号,还有一个叫ckpt count的一个参数。还有别的检查等以后详细说明,在此判断后,如果数据库是一致的,那就直接打开,如果出现不一致,那就再做相应的介质或者实例恢复。
5、数据库关闭的几种方式:
关闭数据库有四种方式,下面我一一列举出来,
1) shutdown abort —— 一般不用这个来关闭数据库,这个是相当于直接断电。跟那个实例失败(instance failure)或者 startup force 一样。。。(相老师说用shutdown abort 之后去冷备数据库,备完了肯定不能用。)直接杀死进程,已经修改的缓冲区数据不会写到数据文件中,没没有提交的事务也不会有时间回滚。(abort 流产,堕胎,使终止)
2)shutdown immediate —— ,执行它后, 不再允许新的connection往上连接, 上来就kill session,也不会等待事务结束,未提交的事务立即回滚。会做一个完全检查点(检查点分两种,有增量和完全两种,以后细谈)。把缓冲区内的所有脏块都写入磁盘。
3)shutdown transactional——等到当前事务关闭以后在关闭数据库,缺点是如果有的事务迟迟不提交,那就不能关闭数据库了,所以一般也不用,还有一点要注意,如果用这个,迟迟没提交,你着急了,就ctrl+c 一下,这样是十分十分危险的,控制文件 很容易被损坏。
4)shutdown normal ——
6、listener初识:
可以认为listener与数据库是独立分开的, 但是listener和数据库之间是有通信的,listener 有两种注册方式:动态注册和静态注册:
详见:http://blog.csdn.net/changyanmanman/article/details/7256255