本译文采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议发布,转载请保留此信息
译者:马齿苋 | 链接:http://www.dbabeta.com/2010/oracle-sql-server-comparison-iii.html
作者:Sadequl Hussain | 原文:http://www.sql-server-performance.com/articles/dba/oracle_sql_server_comparison_iii_p1.aspx

启动与配置参数

在SQL Server安装的时候,同时也会往Windows注册表里面添加一些记录,这些注册表键值指定了实例所需要的各种参数。比如,有的注册表键值指定了错误日志的保存目录,另外的指定了默认的备份目录等等。SQL Server在运行的过程中会使用到这些注册表键值。另外还能给SQLSERVER.EXE指定一些启动参数,包括追踪标志(trace flags),这些附加的参数决定了实例启动之后的行为。除了注册表键值和启动参数之外,SQL Server还包括大量的内部配置参数,用于对实例进行调优。比如说“max server memory”就属于这些参数之一,它可用来调整实例所能使用的最大内存。不用说了,这些系统配置参数也是保存在系统元数据表(system metadata tables)中的。

下面例举的方法都可以用来修改SQL Server配置参数:

  * 使用系统存储过程sp_configure
  * 使用Management Studio或是Enterprise Manager的服务器属性对话框
  * 使用各种层面(facets)组件(2008)或外围应用配置器(Surface Area Configuration)工具(2005)

Oracle的配置参数来自两个对于启动实例和打开数据库都是非常重要的操作系统文件,第一个文件是初始化参数文件 (initialisation parameter file),第二个是控制文件(control file)。初始化参数文件所包含的参数决定怎么样创建实例。记住Oracle实例只包含内存结构和后台进程。参数文件包含的值决定了Oracle要给自己分配多少内存,可以同时有多少用户可以连接到数据库等等。Oracle在读取到这个文件之后才会在内存中建立数据库实例。

参数文件可以是一个纯文本的ASCII文件或者是二进制文件,纯文本参数文件称为pfile,名字为init.ora,其中的SID就是实例的SID了(参照“实例名与SID”小节)。二进制参数文件称为spfile,名字为spfile.ora。纯文本参数文件和二进制参数文件之间最大的差别就是当使用pfile的时候,Oracle只在实例启动的时候读取一次,后续对pfile的修改都要等到实例重启之后才能生效。而使用spfile时,Oracle能在实例运行期间修改其内容。在本文写作之时,Oracle 11g已经有超过250个的初始化参数了,不过还好,作为DBA你是不需要挨个的去设置这些参数的,你只需要配置那么十来个参数就可以保证实例正常使用了,大多数参数值都会使用Oracle默认的设定值。你可以通过Oracle Enterprise Manager Database Control(稍后细说)或者是手工的修改这些初始化参数,手工方法即时通过ALTER SYSTEM命令来修改spfile,使用pfile时,DBA可以直接使用文本编辑器进行修改。(译注:不管是使用pfile还是spfile,都能够使用ALTER SYSTEM命令修改这些参数,只是使用pfile时这些参数的修改是无法保存下来的,同时能修改的也只是一些动态的参数,而使用spfile则可以将这些修改保存到spfile文件中永久保留下来。)

控制文件是实例启动之后Oracle第二个要读取的文件。控制文件所存放的位置也是由参数文件中的参数来指定的。控制文件是一个很小的二进制文件,它包含了与数据库相关的关键的信息,其中包括数据文件和重做日志文件的名字与位置、表空间信息以及检查点信息,Oracle使用控制文件来找到数据文件,然后才能打开供用户访问。控制文件损坏或者是不存在的话数据库都是无法打开的。考虑到控制文件的重要性,通常的做法都是设置多份相同的控制文件拷贝以保证容错能力,多路控制文件中的所有控制文件都会同时的被更新。

最后,第三种Oracle数据库要使用的文件就是密码文件(password file)了,这个文件保存了拥有启动和关闭数据库权限的用户帐户的用户名和密码,稍后会细说。


更改系统元数据和参数配置

不管是Oracle还是SQL Server,系统元数据表、文件、注册表键值或是配置参数都会在用户或者是应用访问数据库并作出变更的时候由数据库引擎自动做出相应的修改。比如说,当在数据库中新建表时,数据库引擎会在系统表中增加相应的行;当DBA修改参数值时,更新也会被捕捉并更新到表中或是文件中。

在SQL Server中,更改系统元数据的操作包括:

  * DDL操作:创建、修改、删除数据库或者数据库对象。
  * 修改系统配置参数(不管是用sp_configure或是GUI)。
  * DCL(数据控制语言,Data Control Lanuage)操作:登陆、认证、证书、代理或者是新建、更新、删除数据库用户。
  * SQL Server配置管理器:当SQL Server或是代理服务数据变更。
  * 系统级变更:创建、修改或者删除连接服务器(link server)、端点(end-point)、Service Broker组件。

在Oracle中,更改数据字典、控制文件或是参数文件的操作包括:

  * DDL操作:创建、更改、删除表空间、数据文件或者是数据库对象。
  * DCL操作:创建、更改、删除用户账户;给用户授予角色、权限。
  * 使用ALTER SYSTEM命令或者是用Enterprise Manager Database Control修改初始化参数。
  * 用Enterprise Manager Database Control或者是ALTER DATABASE命令修改数据库的状态。
  * 备份配置或执行备份操作。

最后,SQL Server中可以使用sp_configure存储过程或是服务器属性对话框(仅部分参数)查看配置参数。
1 sp_configure 'max server memory'

在Oracle中,可以通过执行SHOW PARAMETER命令或是使用Enterprise Manager Database Control查看初始化参数。
1 show parameter sga_target;

动态视图

除了数据字典视图之外,Oracle还提供大量称为动态性能视图(Dynamic Performance Views)的视图,这些视图可以用来查看实例的内存结构或者是控制文件的内容。与数据字典视图不同的是,动态性能视图的内容不是来自于静态的数据表,而是来自服务器内存中实时的数据。这些数据在实例启动的时候开始积累,贯穿于整个实例的生命周期之内,在实例重启或是关闭的时候消失。另外一个不同点就是DBA只能在数据库打开并在线的时候才能查看数据字典视图,而动态性能在实例启动运行之后就能够查看了。部分的动态性能视图只能在数据库MOUNT之后才能查看。这些视图常被称为V$视图,因为它们的名字都是以V$开头的。例如,下面的查询可以显示Oracle实例使用的初始化参数:
1 SELECT NAME, DESCRIPTION, VALUE FROM v$system_parameter;

下面的查询显示当前会话相关的信息:
1 SELECT USERNAME, COMMAND, SCHEMANAME, OSUSER, MACHINE FROM V$SESSION;

在SQL Server 2005中,动态管理视图(Dynamic Management Views, DMV)也同样可以显示实例内存中大量信息。和Oracle动态性能视图一样,DMV也不存在对应的数据表,也在系统重启之后会重新记录。DMV属于SYS架构 (schema),名字以”dm_”开头,下面的代码显示SQL Server实例当前的会话情况:
1 SELECT * FROM sys.dm_exec_requests

存储的物理和逻辑结构

不管是SQL Server的数据库还是Oracle的表空间,它们的物理形态都是存在于主机操作系统下的一系列文件。存在于数据库中的表、视图、索引之类的对象也只有数据库引擎才能识别,这些逻辑对象在物理文件中都是按照一定格式排列,且能被数据库存储引擎所读取。不必说的是,这些逻辑对象和物理文件的内容也是数据库引擎所维护的。

就所涉及到页或者区这方面,SQL Server一直以来都变化不大。数据库页(database page)是SQL Server存储分配和I/O操作的最小单位,一个页大小为8KB。在一个页中,页头占96字节,页头包含了诸如页类型、剩余空间之类的信息。页头之后就是存储的数据行了,跟着的是一些空闲的空间。在页最后是行偏移部分,页中每个数据行都会在行偏移部分有条记录,它记录的是每行开头相对于页的起始点的偏移量。

SQL Server中不同类型的页有着不同的功能。一般来说数据行包含在数据页中,索引记录存储在索引页中,诸如xml、image、text、 varchar(max)或nvarchar(max)之类的特殊类型存储在image或是text之类的特殊页中。当中还有一些像GAM、IAM、 PFS之类的特殊页,下面会一一细说。

页是I/O操作和存储的最后单位,而空间则是以区的形式分配。一个数据库区的大小是固定的:它包含8个物理上连续的页,也就是64KB的结构,每1M的数据库空间都是由16个区数构成的。

区可以进一步分成两类:统一区(uniform)或 混合区(mixed)。在一个统一区中,全部8个页都是来自同一个类似表或是索引之类的对象;在一个混合区中,页可以从属于不同的对象。在创建表或是索引时,通常都是从混合区中分配页。在表或索引的数据增长到足够填满8个或更多页的时候,就会自动的切换到统一区中去。

SQL Server将区分配给各种对象,并通过一些特别的数据库页来跟踪区的使用情况,这些特别的页和普通的存储数据行的数据页不一样,它们更像是一个位图映射 (bitmap)表,每个位(bit)都对应着一个区。

全局分配映射页(Global Allocation Map, GAM)用于跟踪区的使用情况,每个GAM页可以跟踪64000个区或者说4GB的数据。在GAM页中,如果某个位值为0,则表示它所对应的区已经分配给了某个对象使用,值为1时表示这个区是空闲的。这个其实就和Oracle的表空间的本地管理模式(稍后开讲)是一样的。

共享全局分配映射页(Shared Global Allocation Map, SGAM)功能和GAM是一样的,所不同的就是SGAM是用来管理混合区的。不过它的位图映射关系正好是相反的:在GAM中设置为1的,在SGAM中设置为0——用于代表一个空闲的区。

位图映射的概念同样也用在页可用空间(Page Free Space, PFS),这种页记录了某个页是否分配给了某个对象,并且记录这个页上有多少可用的空间,位图映射值可显示一个页的使用率是50%、85%、95%或是95%以上。SQL Server根据这个信息来决定是否要给一行数据分配新的空间。

最后要说的是索引分配映射页(Index Allocation Map, IAM),SQL Server使用这种页来跟踪分配给索引的区的使用情况。在一个表使用了聚集索引的时候,表中的数据行以及对应的数据页都是按照索引键的顺序来存储的,而索引本书是存储在索引页中,聚集索引的数据页由双向链表相互链接,整个索引也是B-树(平衡树)结构的。

当表上没有建立聚集索引时,则称之为堆(heap),堆中的数据行不会有特别的存储顺序,堆表中的数据页同样也没有特别顺序,相互之间也不存在链接。SQL Server是通过扫描IAM页来查找数据页,基本上SQL Server是先从堆的第一个IAM开始扫描,找到页上定义的所有区,然后再转向堆中下一个IAM页,就这样一直重复下去,直到数据文件中(译注:跟堆表相关的所有数据文件)的所有IAM页都扫描完毕才停止。

SQL Server数据文件中预定义了一序列的特殊页,如下图所示:

在数据文件的最开始是数据文件头也,接着是PFS页,再接着是GAM页、SGAM页和IAM页。SQL Server通过这种结构知道自己该怎么去查找一个数据文件。

在Oracle中,数据库中最高级别的逻辑结构就是表空间了,表空间由称为段(segment)的逻辑结构组成,段是给逻辑对象分配存储空间时的单位。在表空间中可以存在各种类型的段,包括表、索引、UNDO等等。表空间和段之间的关系是一对多的:一个表空间可以包含多个段,一个段只能对应于一个表空间。

段的空间是以区(extents)分配的,Oracle中区的概念和SQL Server十分类似。当在表空间中创建一个段时,会先至少分配一个区,当需要更多空间的时候,再在段中分配更多的区。段和区的关系也是一对多的:一个区之能从属于一个段。

Oracle中区同时还扮演着关联逻辑对象和物理结构的角色,它是Oracle数据文件的最小分配单位。同样的数据文件和区之间的关系也是一对多的:一个数据文件可以包含很多个区,但是一个特定的区只能从属于一个特定的文件,区是不能够跨文件的。

目前为止我们了解的Oracle结构可以总结如下:一个数据库会包含多个表空间,一个表空间可能包含一个或多个数据文件用于对象存储,每个表空间同时也会包含多个段,同样这些段中又会包含一个或多个的区。数据文件由区构成:每个区从属于某个特定的段,并且存在于某个特定数据文件中。逻辑段和物理文件之间的关系是多对多的关系:一个段可以包含多个区,每个区则从属于某个特定的数据文件。

在往下,在区中的数据存储在一个个连续的数据块(data blocks)中。数据块是Oracle中最小的 I/O和数据存储单位,这点和Microsoft SQL Server的页是一样的。如果你觉得区和数据块之间的关系是一对多的话,那你就对了。

SQL Server数据页和Oracle数据块之间一个很有意思的差别就在于它们的大小,在SQL Server中,各个版本中页的大小都是一样的:8KB,而且不能修改。而在Oracle中,在创建数据库的表空间的是时候会提供一个默认的块大小,不过也可以不用它。你可以在数据库中新建一个不同于其他表空间块大小的表空间,只不过一旦表空间创建之后,块大小就不能再变了。

另一个存在于SQL Server和Oracle之间的存储差异就是区的管理方式。因为区是在段中分配的,它的管理方式可以通过数据字典或是在表空间本地来完成。

过去的Oracle使用的都是基于字典的区分配管理(dictionary managed extent allocation)。与SQL Server系统表类似,Oracle的数据字典是一个系统元数据的集中仓库。当时字典管理区时,每个区的创建、分配、回收、删除都会被记录到数据字典中的系统表中,在表上产生相应的IO操作。

Oracle已经不再鼓励用户使用字典管理的方法了,代之于本地区分配管理(locally managed extent allocation),这种管理方法是在表空间里面维护一个显示区可用与否的位图,这个和SQL Server的GAM页很相像。位图中的每一位代表一个数据块或者区(在表空间使用统一大小的自动区管理时),在区分配或收回的时候自动的更新位图信息。

考虑到兼容性的因素,字典管理的方法依然存在,DBA可以在创建表空间的时候任意选择这两种方法中的一种。

我这里不再深入的讨论索引的存储结构了,不过在这里再说下Oracle和SQL Server的最后一个差别。因为Oracle可以在多种不平台使用,它的数据库可以使用到各类操作系统的文件系统:比如在Windows 上,Oracle可以安装在NTFS的卷上。Oracle还提供了独立于操作系统而自己来管理物理存储的机制,实现这种机制依赖的是高级存储管理(Advanced Storage Management, ASM),Microsoft SQL Server就没有这种东西了:它的存储引擎利用的是Windows文件系统,而且这个产品只能在Windows平台上使用。

启动和关闭

Microsoft SQL Server和Oracle的启动和关闭顺序是不一样的。在SQL Server中,注册表键值、跟踪标志以及系统配置值对系统启动有着很大的影响。在启动过程中,要加载一系列的DDL、建立内存结构、打开监听端口等等一序列的操作。不看错误日志的,这个过程是没有什么特别的东西的。一般来说DBA可以通过[控制面板]->[服务管理](SQL Server 2000及之前的版本)或者是配置管理器(SQL Server 2005及之后的版本)来启动SQL Server服务。你还可以在命令行中直接运行sqlserver.exe来进行特殊的启动,比如说使用-m参数启动到单用户模式,使用-f参数启动到最小配置模式。

要启动Oracle时,DBA只需要在SQL*PLUS或是其他查询工具中执行一个简单的命令:STARUP。然后启动进程就会先读取Oracle参数文件,然后创建相应的内存结构,启动后台进程。这个阶段之时启动了数据库实例但是并没有打开数据库。下一个阶段是mount数据库,当数据库mount之后,Oracle打开数据库控制文件,读取里面的内容,定位到数据库文件。在第三个阶段,也是最后一个,打开数据库。如果上一次数据库没有按照正常流程关闭的话,此时的数据文件是不同步的(译注:说不一致更准确),这样在打开数据库的阶段就要对未完成的事务进行回滚,对完成了的事务进行前滚。在这阶段的最后,用户就可以使用数据库了。

为方便诊断问题,你可以一步步的执行这些步骤,下面的命令就只创建一个实例:
1 STARTUP NOMOUNT;

如果成功了,就可以让Oracle使用下一个命令加载控制文件了:
1 ALTER DATABASE MOUNT;

一旦数据库mount之后,使用下面最后一个命令打开数据:
1 ALTER DATABASE OPEN;

可以想象,如果Oracle会在启动过程中出问题的话,只要你一步步的执行上面的命令,就能很容易的定位到问题源。这个和在命令行中加上追踪标志及其它参数启动SQL Server差不多。

要正常关闭SQL Server时,你可以在Windows控制面板的服务管理器重停掉SQL Server服务,不过推荐使用配置管理器来操作。停掉服务时,SQL Server会在停掉所有连接关闭之前会确保所有包括数据和日志的更改都已经写入到操作系统文件中。你也可以在查询分析器或是Management Studio中执行SHUTDOWN命令来关闭数据库,使用SHUTDOWN命令的时候可以加上WITH NOWAIT语句,当使用了WITH NOWAIT时,SQL Server会立即停止,不再进行必要的检查点操作,这样关闭后SQL Server需要再下次启动时回滚未完成的事务。

如果你猜Oracle也是可以用一个SHUTDOWN命令来关闭数据库的话,恭喜你,又猜对了。不过Oracle的SHUTDOWN还有四个不同的选项。

如果你执行的是SHUTDOWN ABORT,那这个和SQL Server的SHUTDOWN WITH NOWAIT是一样的。这就相当于拔掉服务器的电源或者是关掉开关,Oracle来不及执行检查点操作,文件也就没有更新,日志也没有写入到磁盘中。

执行SHUTDOWN IMMEDAITE会让Oracle关闭所有没有活动事务的连接,并拒绝新的连接进来。有活动事务的连接则会在完成事务回滚之后被关闭,然后数据库关闭。

如果你希望数据库在现有的活动事务完成之后再关闭的话,则可以执行SHUTDOWN TRANSACTIONAL命令,这个命令和SHUTDOWN IMMEDAITE类似,不同的是会等待正在进行的事务完成而非强行终止。

一般DBA都不会去用的一个命令就是SHUTDOWN NORMAL(译注:这个命令和直接用SHUTDOWN 等价)了,这个命令会导致数据库拒绝新的会话,但是Oracle会等到所有的用户都断开自己的连接之后才会关闭数据库。这是和其他方法不一样的地方,Oracle不会强制结束现有的会话。

除SHUTDOWN ABORT之外,其他三种方法都能够让Oracle数据库在保证数据一致性的情况下关闭。Oracle干净的关闭之后,所有未完成的事务都会回滚,检查点进程会更新数据文件,日志记录也会写入到磁盘当中去,最后在更新完文件头(译注:更新相应的检查点信息)之后再关闭所有文件(译注:即关闭数据库)。