DM8使用了磁盘上大量的物理存储结构来保存和管理用户数据。典型的物理存储结构包括:用于进行功能设置的配置文件;用于记录文件分布的控制文件;用于保存用户实际数据的数据文件、REDO日志文件、归档日志文件、备份文件;用来进行问题跟踪的跟踪日志文件等(见图2-2)。
图2-2 DM8物理存储结构示意图
配置文件是DM8用来设置功能选项的一些文本文件的集合,配置文件以ini为扩展名,它们具有固定的格式,用户可以通过修改其中的某些参数取值来达成以下目标。
● 启用/禁用特定功能项。
● 针对当前系统运行环境设置更优的参数值以提升系统性能。
常用的配置文件有数据库服务配置文件dm.ini、dmmal.ini、dmarch.ini、dm_svc.conf和sqllog.ini;还有数据复制配置文件dmrep.ini、dmllog.ini和dmtimer.ini。各配置文件的参数含义及默认值见附录A。
每个DM8都有一个名为dm.ctl的控制文件。控制文件是一个二进制文件,它记录了数据库必要的初始信息,其中主要包含以下内容。
● 数据库名称。
● 数据库服务器模式。
● OGUID唯一标识。
● 数据库服务器版本。
● 数据文件版本。
● 数据库的启动次数。
● 数据库最近一次的启动时间。
● 表空间信息,包括表空间名、表空间物理文件路径等,记录了所有数据库中使用的表空间,以数组的方式保存起来。
● 控制文件校验码,校验码由数据库服务器在每次修改控制文件后计算生成,保证控制文件的合法性,防止文件损坏及手工修改。
在服务器运行期间,执行表空间的DDL等操作后,服务器内部需要同步修改控制文件内容。如果在修改过程中服务器故障,可能会导致控制文件损坏,为了避免出现这种情况,在修改控制文件时系统内部会执行备份操作。
控制文件的备份过程如图2-3所示。在修改控制文件dm.ctl之前,要预先备份控制文件,若dm.ctl修改失败或中途出现故障,则保留预先备份的控制文件,确定控制文件dm.ctl修改成功后,再将预先备份的控制文件删除,并根据dm.ini中指定的CTL_BAK_PATH/CTL_BAK_NUM对最新的dm.ctl执行事后备份(也就是备份修改成功的控制文件)。若用户指定的CTL_BAK_PATH是非法路径,则不再生成备份文件,在路径有效的情况下,生成备份文件时根据指定的CTL_BAK_NUM判断是否删除以往备份文件。
图2-3 控制文件的备份过程
注意,若dm.ctl文件存放在裸设备上,则预先备份不会生效;若指定的CTL_BAK_PATH是无效路径,则事后备份也不会生效;若预先备份和事后备份的条件都满足,则都会生效执行,否则只执行满足条件的备份策略,若都不满足,则不会再生成备份文件;若是初始化新库,则在初始化完成后,会在SYSTEM_PATH/CTL_BAK路径下对原始的dm.ctl执行一次备份。
数据文件以dbf为扩展名,它是数据库中最重要的文件类型,一个DM数据文件对应磁盘上的一个物理文件,数据文件用于存储真实数据,每个数据库至少有一个与之相关的数据文件。在实际应用中,通常有多个数据文件。
当DM的数据文件空间用完时,它可以自动扩展。可以在创建数据文件时通过MAXSIZE参数限制数据文件的扩展量,当然也可以不限制。但是,数据文件的大小最终会受物理磁盘大小的限制。在实际使用中,一般不建议使用单个巨大的数据文件,为一个表空间创建多个较小的数据文件是更好的选择。
数据文件按照在数据库中的作用不同,可以分为一般数据文件、回滚(ROLL)数据文件和临时(TEMP)数据文件。
(1)一般数据文件。
一般数据文件主要用于存放数据表中的数据。数据文件在逻辑上按照页、簇和段的方式进行管理,详细结构请参考2.3节内容。
(2)回滚数据文件。
ROLL表空间的dbf文件被称为回滚数据文件。回滚数据文件用于保存系统的回滚记录,提供事务回滚时的信息。回滚数据文件整个是一个段。每个事务的回滚页在回滚段中各自挂链,页内则顺序存放回滚记录。
(3)临时数据文件。
temp.dbf是临时数据文件,临时数据文件可以在dm.ini中通过TEMP_SIZE配置大小。
当数据库查询的临时结果集过大,缓存已经不够用时,临时结果集就可以保存在temp.dbf文件中,供后续运算使用。系统中用户创建的临时表也存储在临时数据文件中。
数据文件按数据组织形式可以分为以下4种。
(1)B树数据。
行存储数据是应用最广泛的存储形式之一,其数据是按B树索引组织的。普通表、分区表、B树索引的物理存储格式都是B树。
一个B树包含两个段:一个内节点段,存放内节点数据;一个叶子段,存放叶子节点数据。其B树的逻辑关系由段内页面上的记录通过文件指针来完成。
当表上没有指定聚簇索引时,系统会自动产生一个唯一标识ROWID作为B树的键(key)来唯一标识一行。
(2)堆表数据。
堆表的数据是以挂链形式存储的,一般情况下,最多支持128个链表,一个链表在物理上就是一个段,堆表采用的是物理ROWID,在插入过程中,ROWID在事先已确定,并保证其唯一性,因此可以并发插入,该插入方式效率很高,且由于ROWID是即时生成的,无须保存在物理磁盘上,也节省了空间。
(3)列存储数据。
列存储数据是指数据按列方式组织存储,每个列包含两个段,一个段存放列数据,另一个段存放列的控制信息,读取列数据时,只需要顺序扫描这两个段。在某些特殊应用场景下,其效率要远远高于行存储。
(4)位图索引。
位图索引与B树索引不同,每个索引条目不是指向一行数据,而是指向多行数据的。每个索引项保存的是一定范围内所有行与当前索引键值映射关系的位图。
日志文件记录数据库中的每个操作。按照用途的不同分为REDO日志文件、归档日志文件、逻辑日志文件、物理逻辑日志文件、跟踪日志文件和事件日志文件等。
DM8可以在非归档模式和归档模式下运行。非归档模式下,数据库会将REDO日志写入REDO日志文件中进行存储;归档模式下,数据库会同时将REDO日志写入REDO日志文件和归档日志文件分别进行存储。
在DM8中添加、删除、修改对象,或者改变数据时,DM8都会按照特定的格式,将这些操作执行的结果写入当前的REDO日志文件(重做日志文件)。REDO日志文件以log为扩展名。每个DM8实例必须至少有两个REDO日志文件,默认的两个日志文件为DAMENG01.log、DAMENG02.log,这两个文件循环使用。
REDO日志文件是数据库正在使用的日志文件,因此也被称为联机日志文件。创建数据库时,REDO日志文件通常会被扩展至一定长度,其内容则被初始化为空,当系统运行时,该文件逐渐被产生的日志所填充。对日志文件的写入是顺序且连续的。然而,系统磁盘空间总是有限的,系统必须能够循环利用日志文件的空间,为了做到这一点,当所有日志文件空间被占满时,系统需要清空一部分日志以便重用日志文件的空间。为了保证被清空的日志保护的数据在磁盘上是安全的,这里需要引入一个关键的数据库概念——检查点。当产生检查点时,系统将系统缓冲区中的日志和脏数据页都写入磁盘,以保证当前日志所保护的数据页都已安全写入磁盘,这样日志文件即可被安全重用。
REDO日志文件主要用于数据库的备份与恢复。理想情况下,数据库系统不会用到REDO日志文件中的信息。然而,现实世界总是充满了各种意外,如电源故障、系统故障、介质故障,或者数据库实例进程被强制终止等,数据库缓冲区中的数据页会来不及写入数据文件。这样,在重启DM实例时,通过REDO日志文件中的信息,就可以将数据库的状态恢复到发生意外前的状态。
REDO日志文件对于数据库是至关重要的。它们用于存储数据库的事务日志,以便系统在出现系统故障和介质故障时能够进行故障恢复。在DM8的运行过程中,任何修改数据库的操作都会产生REDO日志。例如,当一条元组插入一个表中时,插入的结果会写入REDO日志文件,当删除一条元组时,删除该元组的操作也被写了进去,这样,当系统出现故障时,通过分析REDO日志可以知道在故障发生前系统做了哪些操作,以及重做哪些动作可以使系统恢复到故障前的状态。
归档日志文件指的是在归档模式下,REDO日志被连续写入归档日志后,所生成的日志文件。归档日志文件以归档时间命名,扩展名也是log。但只有在归档模式下运行时,DM8才会将REDO日志写入归档日志文件。采用归档模式会对系统的性能产生影响,然而系统在归档模式下运行会更安全,当出现故障时其丢失数据的可能性更小,这是由于一旦出现介质故障,如磁盘损坏时,利用归档日志,系统可被恢复至故障发生的前一刻,也可以还原到指定的时间点,而若没有归档日志文件,则只能利用备份进行恢复。归档日志文件还是数据守护功能的核心,数据守护中的备库就是通过重做归档日志中的REDO日志来完成与主库的数据同步的。
如果在DM8上配置了复制功能,复制源就会产生逻辑日志文件。逻辑日志文件是一个流式的文件,它有自己的格式,且不在第1章所述的页、簇和段的管理之下。
逻辑日志文件的内部存储按照复制记录的格式,一条接一条记录存储着复制源端的各种逻辑操作,用于发送给复制目的端。
物理逻辑日志是按照特定格式存储服务器的逻辑操作的日志,专门使用DBMS_LOGMNR包挖掘并获取数据库系统的历史执行语句。当开启记录物理逻辑日志的功能时,这部分日志内容会被存储在REDO日志文件中。
要开启物理逻辑日志的功能,需要满足以下两个条件。
(1)要设置RLOG_APPEND_LOGIC为1、2或者3。
(2)通过设置参数RLOG_IGNORE_TABLE_SET=1或者在建表(或修改表)时指定ADDLOGICLOG开启。若需要记录所有表的物理逻辑日志,则将INI参数RLOG_IGNORE_TABLE_SET设置为1即可;若只需要记录某些表的物理逻辑日志,则要将INI参数RLOG_IGNORE_TABLE_SET设置为0,并在建表或者修改表的语法中使用ADDLOGICLOG。
用户在dm.ini中配置SVR_LOG参数和SVR_LOG_SWITCH_COUNT参数后就会打开跟踪日志。跟踪日志文件是一个纯文本文件,以“dm_commit_日期_时间”命名,默认生成在DM安装目录的log子目录下,管理员可通过INI参数SVR_LOG_FILE_PATH设置其生成路径。
跟踪日志中包含系统各会话执行的SQL语句、参数信息、错误信息等。跟踪日志主要用于分析错误和分析性能,基于跟踪日志可以对系统运行状态进行分析,例如,可以挑出系统现在执行速度较慢的SQL语句,并对其进行优化。
系统中SQL日志的缓存是分块循环使用的,管理员可根据系统执行的语句情况及压力情况设置恰当的日志缓存块大小及预留的缓存块数量。当预留的缓存块数量不足以记录系统产生的任务时,系统会分配新的、用后即弃的缓存块,但是总的空间大小由INI参数SVR_LOG_BUF_TOTAL_SIZE控制,管理员可根据实际情况进行设置。
打开跟踪日志文件会对系统的性能产生较大影响,一般在查错和调优时才会将其打开,默认情况下系统是关闭跟踪日志文件的。若需要跟踪日志但对日志的实时性没有严格的要求,又希望系统有较高的效率,则可以设置参数SQL_TRACE_MASK和SVR_LOG_MIN_EXEC_TIME,只记录关注的相关记录,减少日志总量;设置参数SVR_LOG_ASYNC_FLUSH打开SQL日志异步刷盘则能够提高系统性能。
DM8系统在运行过程中,会在log子目录下产生一个以“dm_实例名_日期”命名的事件日志文件。事件日志文件能够对DM8运行时的关键事件,如对系统启动、关闭、内存申请失败、I/O错误等一些致命错误进行记录。事件日志文件主要用于在系统出现严重错误时对问题进行查看并定位。事件日志文件随着DM8服务的运行一直存在。
事件日志文件打印的是中间步骤的信息,因此出现部分缺失属于正常现象。
备份文件以bak为扩展名,当系统正常运行时,备份文件不会发挥任何作用,它也不是数据库必需的联机文件类型之一。然而,没有数据库系统能够保证永远都正确无误地运行,当数据库出现故障时,备份文件就显得尤为重要了。
当客户利用管理工具或直接发出备份的SQL命令时,DMServer会自动进行备份,并产生一个或多个备份文件,备份文件自身包含了备份的名称、对应的数据库、备份类型和备份时间等信息。同时,系统还会自动记录备份信息及该备份文件所处的位置,但这种记录是零散的,用户可根据需要将其复制到任何地方,并不会影响系统的运行。
调用系统存储过程SP_START_CAPTURE和SP_STOP_CAPTURE可以获得数据重演文件。数据重演文件用于数据重演,存储了从对数据库操作抓取开始到结束时DM8与客户端的通信消息。使用数据重演文件可以多次重复抓取这段时间内的数据库操作,为系统调试和性能调优提供了另一种分析手段。