Oracle 数据库向 MS SQL Server 7.0 的迁移(2)

减小字体 增大字体 作者:佚名  来源:本站整理  发布时间:2009-03-16 14:00:13
 索引数据存储参数
  Microsoft SQL Server 中 FILLFACTOR 选项和 Oracle 中的 PCTFREE 变量的作用基本相
同。随着表的增大,索引页就会拆分,以容纳新数据。索引必须重新组织,来容纳新的数据值
  在索引最初创建时,FILLFACTOR 选项(值从 0 到 100 )控制索引页上保留多少空间。
如果没有指定,使用默认的填充因子 0 - 这将完全填充索引叶级页,并在每个决定节点页上
保留至少一个条目的空间(对于非唯一的聚集索引保留两个)。

  使用较低的填充因子值,最初会减少索引页的拆分,并增加 B 树索引结构中级别的数目
。使用较高的填充因子值,可更有效地使用索引页空间,访问索引数据需要较少的磁盘 I/O,
  PAD_INDEX 选项指定了,将填充因子应用到索引的决定节点页以及数据页中。
  尽管在 Oracle 中,必须调整 PCTFREE 参数来优化性能,但在 CREATE INDEX 语句中,
一般不需要加入 FILLFACTOR 选项。填充因子可用于优化性能。仅当使用现有数据在表上创建
新索引,并且能够准确预估该数据以后的变化时,填充因子才是有用的。
  如果已经把 Oracle 索引的 PCTFREE 设为 0,则考虑使用值为 100 的填充因子。它用
于不发生插入和更新的表(只读表)。填充因子设为 100 时,SQL Server 创建每页均百分
  忽略重复的关键字
  对于 Oracle 和 Microsoft SQL Server,用户不能向唯一索引的列插入重复的值。如果
这样做,就会产生错识消息。但是,使用 SQL Server,开发人员可以选择 INSERT 或
  如果在 CREATE INDEX 语句中指定了 IGNORE_DUP_KEY,并执行了产生重复键的 INSERT
或 UPDATE 语句,SQL Server 就会发出一条警告消息,并忽略(不插入)此重复的行。如果
没有给索引指定 IGNORE_DUP_KEY,SQL Server 就会发出一个错误信息,并回滚整个 INSERT
语句。有关这些选项的详细信息,请参见 SQL Server Books Online。
  Oracle 应用程序可能需要创建只存在很短时间的表。应用程序必须确保,在某些时候可
以删除所有为此目的创建的表。如果应用程序做不到这一点,表空间很快就会变得混乱和难以
  Microsoft SQL Server 提供了临时表数据库对象,它正是为此目的创建的。这些表总是
创建在 tempdb 数据库中。表名称决定了它们在 tempdb 数据库中保留多长时间。

  可以给临时表定义索引。仅能在 tempdb 中显式创建且不带有 # 或 ## 前缀的表上定义
视图。下面的例子给出了,如何创建一个临时表及其相关索引。用户退出时,表和索引被自动
  SELECT SUM(ISNULL(TUITION_PAID,0)) SUM_PAID, MAJOR INTO #SUM_STUDENT
  FROM USER_DB.STUDENT_ADMIN.STUDENT GROUP BY MAJOR
  CREATE UNIQUE INDEX SUM STUDENT IDX ON #SUM STUDENT (MAJOR)
  您可能会发现,使用临时表带来了很多优势,完全有理由为此而修改程序代码。
  Microsoft SQL Server 有一些比 Oracle 更为强健的数据类型。Oracle 和 SQL Server
数据类型之间有多种转换方式。建议使用 DTS 向导自动创建新的 CREATE TABLE 语句。必要
时,可修改这些语句。

  使用 Unicode 数据
  Unicode 规范给世界各地广泛使用的几乎所有字符定义了统一的编码方案。所有计算机使
用该 Unicode 规范,将 Unicode 数据中的位模式统一转换为字符。这就保证了在所有的计算
机上,相同的位模式总是转换成相同的字符。数据可以从一个数据库或计算机自由地传输到另
一个上,而不必担心接收系统不能把位模式正确转换为字符。
  对于每个字符使用 1 个字节编码的数据类型来说,一个问题是这种数据类型只能表示
256 个不同的字符。这就要求对于不同的字母表,必须采用多个编码规范(或代码页)。它也
不能处理像日语 Kanji 或韩国语 Hangul 字母表这样有几千个字符的系统。
  Microsoft SQL Server 使用与 SQL Server 一起安装的代码页中的定义,将 char、
varchar 和 text 列中的位模式转换成字符。客户计算机使用与操作系统一起安装的代码页解
释位模式。有许多种不同的代码页。有些字符在一些代码页中,但不在其它代码页中。有些字
符在一些代码页中用一种位模式定义,在其它代码页中则使用另一种位模式。当创建必须处理
各种语言的国际化系统时,要为所有计算机挑选满足多个国家语言要求的代码页,就变得十分
困难。而且也很难保证,所有计算机与使用不同代码页的系统交互时,能够进行正确转换。
  在 Unicode 规范 中,每个字符使用 2 字节编码,从而解决了这一问题。两字节中有足
够多的不同模式 (65,536),可以使单一规范涵盖大多数通用的商务语言。因为所有的
Unicode 系统均使用相同的位模式表示所有字符,当字符从一个系统迁移到另一个系统时,不
  在 SQL Server 中,nchar、nvarchar 和 ntext 数据类型均支持 Unicode 数据。有关
SQL Server 数据类型的详细信息,请参见 SQL Server Books Online。
  用户定义的数据类型。
  可为 model 数据库或单个用户数据库创建用户定义的数据类型。如果用户定义的数据类
型是为 model 定义的,此后创建的所有新用户数据库均可使用该数据类型。用户定义的数据
类型是用 sp_addtype 系统存储过程定义的。有关详细信息,请参见 SQL Server Books
  可以在 CREATE TABLE 和 ALTER TABLE 语句中使用用户定义的数据类型,并将其与默认
值和规则绑定在一起。表创建过程中,如果使用用户定义的数据类型时,明确地定义了为空性
  此例给出了,如何创建一个用户定义的数据类型。参数为用户类型名称、数据类型和为空
  sp_addtype gender_type, 'varchar(1)', 'not '

  go
  乍看起来,此功能解决了 Oracle 表创建脚本向 SQL Server 迁移的问题。比如,可以方
  sp_addtype date, datetime
  但对于需要大小可变的数据类型,例如 Oracle 数据类型 NUMBER,则没有什么用处。返
  sp_addtype varchar2, varchar
  Go
  Msg 15091, Level 16, State 1
  You must specify a length with this physical type.
  Microsoft timestamp(时间戳)列
  timestamp 列允许 BROWSE 模式更新,并使游标更新操作更为有效。timestamp 是一种数
据类型,每次包含 timestamp 列的行被插入或更新时,它都会自动更新。
  timestamp 中的值不是作为实际的日期或时间存储的,而是以 binary(8) 或
varbinary(8) 存储的,它表示表中行的事件序列。一个表只能有一个 timestamp 列。
  有关详细信息,请参见 SQL Server Books Online。
  Microsoft SQL Server 对象的权限可以授予给其它数据库用户、数据库组和 public 角
色,也可以被其拒绝或撤销。与 Oracle 不同,SQL Server 不允许对象所有者给对象授予
ALTER TABLE 和 CREATE INDEX 权限。这些权限必须只属于对象所有者。
  GRANT 语句在安全系统中创建一个条目,允许当前数据库中的用户处理当前数据库中的数
据或执行特定的 Transact-SQL 语句。在 Oracle 和 SQL Server 中,GRANT 语句的语法是相
  DENY 语句在安全系统中创建一个条目,拒绝当前数据库中安全帐户的权限,并禁止安全
帐户以组或角色成员身份继承权限。Oracle 没有 DENY 语句。REVOKE 语句撤销以前授予当
前数据库中一个用户的权限或被其拒绝的权限。

  有关对象级权限的详细信息,请参见 SQL Server Books Online。
  在 Oracle 中,REFERENCES 权限只能授予一个用户。SQL Server 则允许将 REFERENCES
权限授予数据库用户和数据库组。在 Oracle 和 SQL Server 中,INSERT、UPDATE、DELETE
  实施数据完整性和业务规则
  实施数据完整性确保了数据库中数据的质量。在表的规划中,有两个重要的步骤,即识别
列的有效值,以及确定如何在列中实施数据完整性。数据完整性可以分为四个类别,并用不同
的方法来实施。

  实体完整性把一行定义为特定表的一个单独实体。实体完整性通过索引、UNIQUE 约束、
PRIMARY KEY 约束或 IDENTITY 属性,来实施表的标识符列或主键的完整性。
  约束的命名
  应该始终显式命名约束。如果没有,则 Oracle 和 Microsoft SQL Server 使用不同的命
名规则隐式命名约束。这些命名上的差别会给迁移过程带来不必要的麻烦。在删除或禁用约束
时,就会造成不一致,因为必须使用名称,约束才能被删除。对于 Oracle 和 SQL Server 来
  CONSTRAINT constraint_name
  主键和唯一列
  SQL-92 标准要求,主键中的所有值应该唯一,并且该列不允许有空值。一旦定义了
PRIMARY KEY 或 UNIQUE 约束,Oracle 和 Microsoft SQL Server 通过自动创建唯一索引,
来实施唯一性。此外,主键列自动定义为 NOT NULL。每个表只允许一个主键。
  对主键来说,默认地创建一个 SQL Server 聚集索引,尽管也可以请求非聚集索引。主键
上的 Oracle 索引可以通过删除或禁用该约束来删除,而 SQL Server 索引只能通过删除该约
  在两种 RDBMS 中,均可使用 UNIQUE 约束来定义备用键。在任一表上,均可定义多个
UNIQUE 约束。UNIQUE 约束列可为空。在 SQL Server 中,除非另外指定,默认创建非聚集索
  在迁移应用程序时,要注意,对于完全唯一键(单个或多个列索引),SQL Server 只允
许一行包含 NULL 值,而 Oracle 允许任意数量的行包含 NULL 值。

  增加和删除约束
  禁用约束可以提高数据库性能和简化数据复制过程。例如,在远程站点重建或复制表数据
时,不需要再重复约束检查,因为数据最初插到表中时,数据完整性已经检查过了。可以编写
一个 Oracle 应用程序,禁用或启用约束(除 PRIMARY KEY 和 UNIQUE 外)。在 Microsoft
SQL Server 中,将 ALTER TABLE 语句与 CHECK 和 WITH ONCHECK 选项一起使用,也可实现
  此插图给出了,这一过程的对比。
  
  在 SQL Server 中,可以使用 NOCHECK 子句和 ALL 关键字延迟所有的表约束。
  如果 Oracle 应用程序要使用 CASCADE 选项禁用或删除 PRIMARY KEY 或 UNIQUE 约束,
则可能需要重写一些代码,因为 CASCADE 选项禁用或删除父约束及其相关的任何子完整性约
  下面是该语法的一个示例:
  DROP CONSTRAINT DEPT_DEPT_PK CASCADE
  必须修改 SQL Server 应用程序,使其先删除子约束,然后再删除父约束。例如,要删除
DEPT 表上的 PRIMARY KEY 约束,必须删除列 STUDENT.MAJOR 和 CLASS.DEPT 上的外键。下
  ALTER TABLE STUDENT
  DROP CONSTRAINT STUDENT_MAJOR_FK
  ALTER TABLE CLASS
  DROP CONSTRAINT CLASS_DEPT_FK
  ALTER TABLE DEPT
  DROP CONSTRAINT DEPT_DEPT_PK
  ALTER TABLE 语法(用于增添和删除约束)对 Oracle 和 SQL Server 几乎是相同的。
  产生连续的数值
  如果 Oracle 应用程序使用 SEQUENCE,则可以方便地对它进行修改,来使用 Microsoft
SQL Server IDENTITY 属性。

  尽管 IDENTITY 属性在一个表中自动完成行编号,但不同的表(每个表均有其自己的标识
符列)的属性值可能会相同。这是因为,IDENTITY 属性只保证在使用它的表中唯一。如果应
用程序必须生成一个标识符列,其在整个数据库中、或者甚至每个联网计算机上的每个数据库
中都是唯一,则使用 ROWGUIDCOL 属性、uniqueidentifier 数据类型和 NEWID 函数。SQL
Server 使用全局唯一标识符列,来合并复制,确保在表的多个副本中,行被唯一地标识。
  有关创建和修改标识符列的详细信息,请参见 SQL Server Books Online。
  对于给定列,范围完整性实施了有效的条目。范围完整性是通过限制可能值的类型(通过
数据类型)、格式(通过 CHECK 约束)或范围(通过 REFERENCE 和 CHECK 约束)实施的。
  DEFAULT 和 CHECK 约束
  Oracle 把默认值作为列属性,而 Microsoft SQL Server 把默认值作为约束。SQL
Server DEFAULT 约束可以包含常量、不带参数的内置函数(niladci 函数)或 NULL。
  要方便地迁移 Oracle DEFAULT 列属性,应该在 SQL Server 列级中定义 DEFAULT 约束
,而不必使用约束名称。对于每个 DEFAULT 约束,SQL Server 均生成一个唯一的名称。
  在 Oracle 和 SQL Server 中,定义 CHECK 约束的语法是相同的。搜索条件必须对一个
布尔表达式进行求值,并且不能包括子查询。列级 CHECK 约束只能引用受约束的列,表级
CHECK 约束只可以引用受约束表中的列。可以为一个表定义多个 CHECK 约束。在 CREATE
TABLE 语句中,SQL Server 语法规定,在一个列上只允许创建一个列级 CHECK 约束,约束
  测试修改后的 CREATE TABLE 语句的最好方法是,使用 SQL Server 中的 SQL Server 查
询分析器,并分析该语法。结果窗格给出所有的错误。有关约束语法的详细信息,请参见
SQL Server Books Online。

  有关用户定义的规则和默认值的说明:出于向后兼容的考虑,仍保留 Microsoft SQL
Server 规则和默认值,但对于新的应用程序开发,建议使用 CHECK 和 DEFAULT 约束。有关
  为空性
  Microsoft SQL Server 和 Oracle 创建列约束,来实施为空性。Oracle 列默认为 NULL
,除非在 CREATE TABLE 或 ALTER TABLE 语句中指定了 NOT NULL。在 Microsoft SQL
Server 中,数据库和会话设置可以覆盖列定义中使用的数据类型为空性。
  所有的 SQL 脚本(不论是 Oracle 还是 SQL Server)都应该为每一列显式定义 NULL
和 NOT NULL。要了解这一策略是如何实施的,请参见 Oratable.sql 和 Sstable.sql 示例
表创建脚本。如果没有显式定义,列的为空性遵循下列规则。

  NOT FOR REPLICATION 子句用于复制过程中暂停列级、FOREIGN KEY 和 CHECK 约束的使
  外键
  在每种 RDBMS 中,定义外键的规则是相似的。在外键子句中指定的列的数目和每个列的
数据类型必须和 REFERENCES 子句相符。在该列输入的非空值在 REFERENCES 子句中定义的表
和列中必须存在,并且被引用表的列中,必须有一个 PRIMARY KEY 或 UNIQUE 约束。
  Microsoft SQL Server 约束提供了引用同一数据库中表的能力。要实现跨数据库的引用
  Oracle 和 SQL Server 都支持自引用的表,在该表中引用(外键)指向同一表的一个或
多个列。例如,CLASS 表中的 prereq 列可以引用 CLASS 表中的 ccode 列,以保证输入了有
  Oracle 使用 CASCADE DELETE 子句,来实现级联删除和更新,而 SQL Server 使用表触
发器,来提供相同的功能。有关详细信息,请参见本章后面的“SQL 语言支持”。
  用户定义的完整性允许定义不属于任何其它完整性类别的业务规则。
  存储过程
  Microsoft SQL Server 存储过程使用 CREATE PROCEDURE 语句,接受和返回用户提供的
参数。除临时存储过程外,其它存储过程均在当前数据库中创建。下表给出了其 Oracle 和
SQL Server 语法。

  在 SQL Server 中,临时过程创建在 tempdb 数据库中,对于局部临时过程,在
procedure_name 前加一个数字符 (#procedure_name),全局临时过程前加两个数字符
  局部临时过程只能由创建它的用户使用。运行局部临时过程的权限不能授予其他用户。用
  所有的 SQL Server 用户均可使用全局临时过程。如果创建了全局临时过程,所有的用户
均可以访问它,权限不能被显式地撤销。使用过程的最后一个用户会话结束后,全局临时过程
  SQL Server 存储过程最多可嵌套 32 级。嵌套级在调用过程开始执行时递增,调用过程
  下面的例子给出了,如何使用 Transact-SQL 存储过程替代 Oracle PL/SQL 打包的函数
。Transact-SQL 版本要简单得多,因为 SQL Server 可以直接从存储过程中的 SELECT 语句
返回结果集,而无需使用游标。

  SQL Server 不支持类似 Oracle 包或函数的结构,也不支持创建存储过程的 CREATE
  延迟存储过程的执行
  Microsoft SQL Server 提供了 WAITFOR,它允许开发人员指定触发语句块、存储过程或
事务执行的时间、时间间隔或事件。对于 Transact-SQL 来说,它就相当于 Oracle 的
  WAITFOR {DELAY 'time' TIME 'time'}
  此处
  DELAY
  通知 Microsoft SQL Server 等待,直到指定的时间结束,最多 24 小时。
  'time'
  等待的时间。time 可用 datetime 数据可接受的一种格式来指定,或指定为一个局部变
量。不能指定日期;因此,不允许 datetime 值的数据部分。
  TIME
  通知 SQL Server 等到指定的时间。
  例如:
  BEGIN
  WAITFOR TIME '22:20'
  EXECUTE update_all_stats
  END
  指定存储过程的参数
  要指定存储过程的参数,请使用以下语法:
  
  只能在当前数据库中创建触发器,但可以引用当前数据库之外的对象。如果使用所有者名
  触发器可以嵌套 32 级。如果触发器更改了一个其上有另一触发器的表,第二个触发器就
被启动,并调用第三个触发器,依此类推。如果此链中的某一触发器产生了一个死循环,就会
超出嵌套级,触发器被取消。此外,如果表中一列上的更新触发器导致对另一列的更新,该更
  Microsoft SQL Server 声明引用完整性 (DRI) 不提供数据库之间的引用完整性。如果
需要数据库之间的引用完整性,则使用触发器。
  Transact-SQL 触发器不允许下列语句:
  CREATE 语句(DATABASE、TABLE、INDEX、PROCEDURE、DEFAULT、RULE、TRIGGER、
  DROP 语句(TRIGGER、INDEX、TABLE、PROCEDURE、DATABASE、VIEW、DEFAULT、RULE)
  ALTER 语句(DATABASE、TABLE、VIEW、PROCEDURE、TRIGGER)
  TRUNCATE TABLE
  GRANT, REVOKE, DENY
  UPDATE STATISTICS
  RECONFIGURE
  UPDATE STATISTICS
  RESTORE DATABASE, RESTORE LOG
  LOAD LOG, DATABASE
  DISK 语句
  SELECT INTO(因为它创建一个表)
  有关触发器的详细信息,请参见 SQL Server Books Online。
  事务、锁定和并发性
  此节解释了,在 Oracle 和 Microsoft SQL Server 中,事务是如何执行的,并揭示两种
数据库中锁定过程及并发性问题的差异。
  在 Oracle 中,进行插入、更新或删除操作时,事务自动启动。要把所有的更改保存到数
据库中,应用程序必须执行 COMMIT 命令。如果没有执行 COMMIT,所有的更改都被回滚或自
  默认情况下,Microsoft SQL Server 在每个插入、更新或删除操作之后,自动执行一个
COMMIT 语句。因为数据是自动存储的,所以不能回滚任何更改。可以使用隐性或显性事务模
  隐性事务模式允许 SQL Server 与 Oracle 一样运作,它可通过 SET IMP
LICIT_TRANSACTION ON 语句来启动。如果这个选项是 ON,并且没有任何待处理事务,每个
SQL 语句就会自动启动一个事务。如果有打开的事务,就不能启动新的事务。要使所有的更
改生效并释放所有的锁定,用户必须使用 COMMIT TRANSACTION 语句显式地提交开启的事务。
  显性事务是一组 SQL 语句,它用下列事务分隔符括起来:
  BEGIN TRANSACTION [transaction_name]
  COMMIT TRANSACTION [transaction_name]
  ROLLBACK TRANSACTION [transaction_name savepoint_name]
  在下列示例中,English 系被改为 Literature 系。请注意 BEGIN TRANSACTION 和
COMMIT TRANSACTION 语句的用法。

  所有显性事务都必须包含在 BEGIN TRANSACTION...COMMIT TRANSACTION 语句中。SAVE
TRANSACTION 和 Oracle SAVEPOINT 语句的作用相同,即为事务设定一个保存点,来允许部分
  事务之间可以嵌套。如果是这样,最外面的嵌套对创建和提交事务,里面的嵌套对跟踪嵌
套级。当遇到嵌套的事务时,@@TRANSACTION 函数递增。通常,当带有 BEGINUCOMMIT 对的存
储过程或触发器互相调用时,此明显的事务嵌套发生。尽管事务可以嵌套,但它们对
  在存储过程或触发器中,BEGIN TRANSACTION 语句的数目必须和 COMMIT TRANSACTION 语
句的数目一致。包含不成对的 BEGIN TRANSACTION 和 COMMIT TRANSACTION 语句的存储过程
或触发器执行时就会产生错误信息。如果包含 BEGIN TRANSACTION 和 COMMIT TRANSACTION
语句,语法允许从事务内部调用存储过程和触发器。
  只要可能,应把大的事务分为较小的事务。确保在一批作业中,每个事务都是显式定义的
。要将可能的并发性冲突降到最低,事务不应该跨越多批作业,也不应等待用户输入。把多个
Transact-SQL 语句合到一个长时间运行的事务,会负面地影响恢复时间,并引起并发性问题
  当使用 ODBC 编程时,可以使用 SQLSetConnectOption 函数,选择隐性或显性事务模式
。ODBC 程序选择这种还是那种模式,取决于 AUTOCOMMIT 连接选项。如果 AUTOCOMMIT 设为
ON(默认值),则处于显性模式。如果 AUTOCOMMIT 设为 OFF,则处于隐性模式。
  如果使用 SQL Server 查询分析器或其它查询工具执行一个脚本,则可以在脚本上包含前
面所示的显式 BEGIN TRANSACTION 语句,或者用 SET IMPLICIT _TRANSACTIONS ON 语句启动
脚本。BEGIN TRANSACTION 方法更灵活,但隐式方法与 Oracle 的兼容性更好。
  Oracle 和 Microsoft SQL Server 的锁定和隔离策略大不相同。把应用程序从 Oracle
迁移到 SQL Server 时,必须考虑这些差异,确保应用程序的可伸缩性。
  对于所有读取数据的 SQL 语句,Oracle 均显式或隐式地使用多版本一致性模型。在此模
型中,默认情况下,在读取数据行之前,数据读取者既不获取锁定也不等待其它锁定被释放。
当读取者要请求的数据已经被其他写入者更改但还未提交,Oracle 使用其回滚段重建一个行
  Oracle 中的数据写入者请求锁定被更新、删除或插入的数据。这些锁定一直保持到事务
结束时为止,可防止其他用户覆盖未提交的更改。
  Microsoft SQL Server 具有多粒锁定功能,允许一个事务锁定各种类型的资源。要将锁
定开销降至最低,SQL Server 自动在任务相应的级别上锁定资源。在较小粒度上(例如行)
进行锁定,可提高并发性,但开销更大,因为如果要对多行锁定,就必须保持更多的锁定。在
较大粒度(例如表)上进行锁定,从并发性角度讲是代价很高的,因为对整个表的锁定限制了
其它事务对表任何部分的访问,但是它有较小的开销,因为只需要维护较少的锁定。SQL
Server 可以锁定以下资源(按照粒度增大的顺序排列)。

  在任何 RDBMS 中,快速释放锁定来提供最大并发性,是很重要的。可以将事务尽可能缩
短,以确保快速释放锁定。如果可能,事务不应跨到服务器的多个往返操作,也不应该包括用
户“思考”时间。如果使用游标,还需编写应用程序来快速地提取数据,因为未提取的数据扫
描可能占据服务器上的共享锁定,从而阻碍更新者进行更新。有关详细信息,请参见本章后面
  Microsoft SQL Server 和 Oracle 都允许开发人员请求非默认的锁定和隔离行为。在
Oracle 中,最通常的机制是 SELECT 命令上的 FOR UPDATE 子句、SET TRANSACTION READ
  因为 Oracle 和 SQL Server 的锁定和隔离机制是完全不同的,所以很难将这些锁定选项
在两者之间直接对应起来。要更好地理解这一过程,了解 SQL Server 提供的改变其默认锁定
  在 SQL Server 中,改变默认锁定模式最常用的机制是 SET TRANSACTION ISOLATION
LEVEL 语句,以及 SELECT 及 UPDATE 语句中支持的锁定提示。SET TRANSACTION ISOLATION
LEVEL 语句设定用户会话期间的事务隔离级别。这是会话的默认行为,除非在一个 SQL 语句
的 FROM 子句中在表级指定了锁定提示。事务隔离这样设定:
  SET TRANSACTION ISOLATION LEVEL
  {
  READ COMMITTED
   READ UNCOMMITTED
   REPEATABLE READ
   SERIALIZABLE
  }
  READ COMMITTED
  SQL Server 的默认隔离级别。使用这个选项时,应用程序不能读取还未被其它事务提交
的数据。但是,在这个模式中,只要数据被从页中读取,共享锁定就被释放。如果应用程序在
同一事务中重新读取相同的数据范围,它会看到其他用户的更改。
  SERIALIZABLE
  设定了这个选项,事务就被彼此隔离。如果在查询中不想看到其他用户的更改,应把事务
隔离级别设为 SERIALIZBLE。SQL Server 保持所有的共享锁定,直到事务结束为止。在
SELECT 语句中,在表名之后使用 HOLDLOCK 提示,可以在更细微的级别上获得这一效果。使
用这两个选项,在保证严格的一致性的同时,也降低了并发性,因此只有在必要时才使用。
  READ UNCOMMITTED
  设定了这个选项,SQL Server 读取者就会畅通无阻,这一点与 Oracle 一样。这个选项
实现脏读或隔离级别 0 锁定,这意味着不发出共享锁定,并且不支持排它锁定。这个选项设
定时,就可以读取未提交的或“脏”数据;在事务结束之前,数据中的值可以被改变,数据集
中的行可能出现或消失。这个选项与在事务的所有 SELECT 语句中将所有表上均设定 ONLOCK
有相同的效果。这是四个隔离级别中限制最少的。只有当彻底分析了它怎样影响应用程序中结
果的准确性之后,才能使用这个隔离级别。
  SQL Server 用两种方式支持 Oracle READ ONLY 功能:
  如果应用程序中的一些事务需要可重复读取行为,则可能需要使用 SQL Server 提供的
  如果所有的数据库访问都是只读的,可以把 SQL Server 数据库选项设为 READ ONLY,以
  Oracle 的 SELECTUFOR UPDATE 语句主要在应用程序需要用 WHERE CURRENT OF 语法执行
定位更新或删除游标时使用。在这种情况下,可有选择地删除 FOR UPDATE 子句,因为
  默认情况下,SQL Server 游标不保留提取行的锁定。SQL Server 使用一个优化的并发性
策略,防止更新彼此覆盖。如果用户要更新或删除一行,但该行自读入游标后已被更改,则
SQL Server 发出一个错误消息。应用程序可以捕获该错误消息,相应地重试更新或删除。要
替代这种行为,开发人员可在游标声明中使用 SCROLL_LOCKS。
  在一般情况下,更新者之间冲突很少,乐观的并发性策略可支持较高的并发性。如果应用
程序的确需要确保行在提取后不能被更改,则使用 SELECT 语句中的 UPDLOCK 提示。这个提
示并不阻碍其他读取者读取,但是它防止其他潜在写入者获得数据上的更新锁定。使用 ODBC
时,可以使用 SQLSETSTMTOPTION (U,SQL_CONCURRENCY)= SQL_CONCUR_LOCK 达到这一效果。
  Microsoft SQL Server 可以使用 SELECTUtable_name (TABLOCK) 语句锁定整个表。它与
Oracle LOCK TABLEUIN SHARE MODE 语句执行的操作相同。该锁定允许他人读取表,但是禁
止他们更新。默认情况下,锁定一直保持到语句结束为止。如果还加入了关键字 HOLDLOCK
(SELECTUtable_name (TABLOCK HOLDLOCK)),表锁定一直保持到事务结束为止。
  可以使用 SELECTUtable_name (TABLOCKX) 语句,在 SQL Server 表上设置排它锁定。该
语句请求表上的排它锁定。它用于防止他人读取或更新表,并一直保持到命令或事务结束时为
止。它和 Oracle LOCK TABLEUIN EXCLUSIVE MODE 语句的功能相似。
  在显式锁定请求中,SQL Server 并不提供 NOWAIT 选项。
  当查询从表中请求行时,Microsoft SQL Server 自动生成页级锁定。但是,如果查询请
求占表中很大比例的行,SQL Server 就把锁定从页级升级到表级。这一过程叫做“锁定升级
  锁定升级使表扫描和对大结果集的操作更有效,这是因为它降低了锁定开销。没有
WHERE 子句的 SQL 语句通常引起锁定升级。
  在读操作过程中,当将共享页锁定升级为表锁定时,就会使用共享表锁定 (TABLOCK)。共
  使用 HOLDLOCK 或 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 语句时。
  优化程序选定一个表扫描时。
  表中共享锁定的累计数目超过锁定升级极限时。
  锁定升级极限默认为每表 200 页,但也可以根据表大小,自定义最小和最大极限。共享
表锁定还在创建非聚集索引时使用。有关锁定升级极限的详细信息,请参见 SQL Server
  在写操作过程中,一个 UPDATE 锁定被升级为表锁定时,则应用排它表锁定 (TABLOCKX)
  更新或删除操作没有可用索引时。
  有排它锁定的表中页的数目超过了锁定升级极限时。
  创建聚集索引时。
  如果 Oracle 不能升级行级锁定,在某些包含 FOR UPDATE 子句的查询中,就可能出现问
题。例如,假定 STUDENT 表有 100,000 行数据,并且一个 Oracle 用户执行下列语句:
  SELECT * FROM STUDENT FOR UPDATE
  这个语句迫使 Oracle RDBMS 一次锁定 STUDENT 表一行;这可能要花很长时间。它从不
  在 SQL Server 中,相同的查询是:
  SELECT * FROM STUDENT (UPDLOCK)
  当查询运行时,页级锁定升级为表级锁定,它查询更为有效,并且速度快得多。

Tags:

作者:佚名
分享到: 微信 更多