SQL 问题与解答数据库大小、镜像、标记事务及其他

编辑:Nancy Michell

移动群集

问:对于下面的两个物理服务器,如果将 SQL Server 2000 群集(以及 Windows® 群集和 SQL Server™ 群集)移动到新 IP 地址。我需要重建整个解决方案吗?

答:不需要,您只需要运行 SQL Server 安装程序和修改 IP 地址。下面的知识库文章会介绍详细步骤。

数据库大小

问:我目前使用的 SQL Server 2000 SP4 中有一个差不多 10GB 的关键任务数据库、一个 SIMPLE 恢复模型、一个 9,850MB 的主文件和一个 88MB 的事务日志文件。数据库备份差不多也有 10GB。为了提高性能,我应该减少数据库大小吗?如果是的话,我应该使用 DBCC SHRINKDATABASE 还是 DBCC SHRINKFILE?(问题在于,我没有空闲的非高峰时间来进行这种维护。)

答:只有当数据库经历许多删除和更新并导致数据量变少时,DBCC SHRINKDATABASE 或 DBCC SHRINKFILE 才有帮助。但真正的问题是您为什么会在意这些?目前,10GB 的磁盘只卖 20 来美元。再加大约 100GB 的磁盘空间并运行起来不是更有意义吗?可用空间中的碎片越多,性能越恶化。但如果您不能进行任何维护,您的选择范围就很小了。在这种情况下,有时人们使用数据库的另一个副本。他们通过复制使备份副本保持最新,对备份副本进行维护,然后将应用程序切换到备份副本。显而易见,这需要进行一些代码更改和离开 SIMPLE 恢复模型(到 FULL 或 BULK_LOGGED),这是个很好的长期解决方案。

升级和性能

问:我需要将两个应用程序从 SQL Server 2000 移动到 SQL Server 2005。在升级过程中,我如何才能避免对性能产生不良影响?

答:在升级过程中,下面这些失误通常会造成性能降级,所以应努力避免出现这些错误:

  1. 升级到 SQL Server 2005 后没有重建统计数据。
  2. JOINS 和 WHERE 子句会比较两个不同的数据类型,从而导致性能下降,特别是在服务器以前运行 SQL Server 2000 SP3 或更低版本的情况下(请参阅 support.microsoft.com/kb/271566/)。
  3. SQL Server 2005 实例没有正确配置;内存、地址窗口化扩展插件 (AWE)、驱动程序等均未正确配置。运行 SQL Server 2000 的方框已调整,执行操作的人已离开但未记录,所以在 SQL Server 2005 实例上从未完成过。
  4. 硬件出现故障。购买新硬件常常是因为广告上看起来很好,但在现实生活中却并不实用。

在生产系统中采用 SQL Server 实例之前,应先设立一个性能基准,以确定可实现预期性能。这样会排除可能出现问题的基础结构。另外还需要查看 Perfmon 计数器(如磁盘、I/O 和内存),并在实例之间进行比较。

数据库镜像

问:我目前使用数据库镜像,并想启用 READ_COMMITTED_SNAPSHOT 数据库选项。设置镜像后,我试图启用该选项,但我收到一个异常消息,声明数据库正在镜像会话之中,无法运行该命令。

答:出现这个问题的原因是,设置 READ_COMMITTED_SNAPSHOT 选项后,需要重启数据库才能生效。所以,您需要断开镜像会话,设置选项,然后重启数据库。完成这些步骤后,就可以重建镜像了。建立会话后,镜像数据库可选中该选项,并在发生故障转移时使用。

问:我试图设置异步镜像,但是收到 1418 错误。运行 Netstat -ano 显示 SQL Server 正在监听所有服务器上的正确端口。在我试图启动镜像时显示该错误。这是怎么回事?

答:一种可能性是防火墙拦截了通信;这个问题相对来说比较普遍,您应该进行调查。有关更多帮助,请查阅下面的白皮书:对数据库镜像设置进行故障排除MSSQLSERVER_1418

不过请注意,这个问题不是异步镜像所特有的。事实上,同步镜像也会发生这样的问题。

您收到的错误(“The server network address "%.*ls" cannot be reached or does not exist.Check the network address name and reissue the command”(服务器网络地址 "%.*ls" 无法访问或不存在。请检查网络地址名称,然后重新发布命令))是正确的。通常不是远程合作伙伴不存在,只是无法访问而已。

如果远程合作伙伴停机或未监听端口,甚至端点停机,都可能发生上述问题。(如果远程合作伙伴不能协商相同的加密机制或有一些其他身份验证问题,就可能发生端点停机。)如果发出命令的合作伙伴的防火墙拦截了合作伙伴与外界的通信,也会发生这种故障。

您还要排除一些其他问题,其中包括数据源名称 (DSN) 问题和名称解析问题。通常会建议您使用完全限定域名。所以请记住,如果您的防火墙经常出现问题,肯定是另有隐情。

问:我想使用 SQL Server 2005 镜像;但是,我听说如果在同一 SQL Server 实例上有多个应用程序连接到多个数据库,则不建议使用镜像。是这样吗?

答:事实上,根据您是每个应用程序都有自己的数据库还是多个应用程序使用跨数据库事务或分布式事务处理协调器 (DTC) 事务,答案是不同的。如果使用跨数据库事务,则镜像会引起逻辑矛盾,无法按预期提交事务。有关在此情形下会发生状况的详细讲解,请单击此处

如果多个应用程序使用多个数据库,并且每个应用程序都有自己的数据库,则镜像不会造成这些问题。

标记事务

问:“标记事务”的确切含义是什么?它们是不是可在一个数据库是 SQL Server 而另一个数据库是 Oracle 的情况下使用?

答:标记事务是指 DBA 定期在所有日志中的同一位置放置标记。此操作结合使表格恢复事务标记的能力,允许您将所有数据库恢复到同一点。执行此操作非常痛苦,因为您必须恢复涉及到的所有数据库,还将丢失所有数据库中的数据,因此您必须确保不丢失日志文件,以避免发生问题。标记事务是特定于 SQL Server 的,因此如果您的分布式事务包括非 SQL Server 数据库,这些数据库不能参与事务标记。总的来说,很少有分布式数据库系统使用事务标记。只是将丢失一个事务日志视为灾难性事件,从中恢复需要许多手动工作。

Access-To-T-SQL 转换工具

问:是否有可供存储过程使用的自动执行 Access™-SQL 到 T-SQL 的转换工具?

答:试一下 SQL Server Migration Assistant (SSMA) for Access,点击下载此工具。这里还有 SQL Server Migration Assistant for Oracle、SQL Server Migration Assistant for Sybase 和 Migrating Informix Databases to Microsoft® SQL Server 2000。

要从 Access 升迁到 SQL Server,可使用 Office 升迁向导。但 SSMA for Access(图 1 所示)有更多功能,包括转换评估报告和网络扫描。SSMA for Access 还可以修复目前 Office 升迁向导无法正确处理的许多问题。

图 1 SQL Server Migration Assistant for Access

图 1** SQL Server Migration Assistant for Access **(单击该图像获得较大视图)

非群集索引

问:我有一个表格,其主键由两个 GUID(假设为 GUID1 和 GUID2)构成。在 GUID1 和 GUID2 上已有唯一的群集索引。现在因为性能上的要求,需要在 GUID2 和 GUID1 上创建第二个非群集索引。如果我将该索引声明为唯一,是否会对性能产生影响?

答:将非群集索引声明为唯一不会对性能产生任何负面影响。事实上,这样做会减少索引树层次。

如果将非群集索引声明为非唯一,会将行定位器追加到根页面和非叶页面中索引条目的键部分。这样做是为了方便删除和更新索引条目,如果有键副本,可避免扫描同义字链 — 通过对键加定位器执行系统搜索操作找到要更改的特定条目。结果是这些条目较长(与您选择的群集键相比,这些条目相当长)。因此,根页面和非叶页面自然会更快地填满。如果索引是唯一的,您应如此声明。

要点是,不管表格是否有群集索引,表格中未声明为唯一的任何非群集索引均会将定位器追加到根页面和其他非叶页面中的索引条目。

另外,如果您使用 int 标识符列作为代理键,然后增加两个唯一的索引(GUID1、GUID2)和(GUID2、GUID1),则会改善性能,因为这些索引有 4 字节群集键,而不是 32 字节群集键。

更新锁

问:如果存储过程的结构如下:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION

-- Get The lock if available
UPDATE    ProcessingInstances 
SET       LockHolder = @MessageId
WHERE     ( InstanceId = @InstanceId ) 
AND       ( LockHolder IS NULL )

COMMIT TRANSACTION

此存储过程只允许一个调用者获得锁,任何其他调用者均需等待。我能通过降低隔离级别达到相同的行为吗?

好像 READ COMMITTED 是正确的隔离级别,因为这个事务只有一个查询,如果另一个事务正在更新同一个记录,则这个事务只能等待另一个事务。是这样吗?

答:在您的示例中,不是序列化设置使其他调用者等待,而是更新本身让其他调用者等待。是的,您可以将隔离级别设置为 READ COMMITTED,无论更新使用什么索引,都会自然获得更新锁。这会给执行同一条语句的其他进程造成问题,所以在更新完成之前会阻止其他进程的执行。(另外,如果更新是唯一的语句,则不需要显式事务;如果语句不在显式事务中,则每个语句在其自己的事务中是隐式的。)

但是,如果 UPDATE 语句中没有与 WHERE 子句相匹配的行,则使用序列化隔离级别可防止其他事务插入或修改这样的行。如果您要在 READ COMMITTED 隔离级别中运行 UPDATE,就不会发生上述问题,其他事务也能够引入适合于更新的行。如果存储过程代码确实是如您所示的代码,则采取这些措施(序列化或事务)没有什么意义;您只需执行更新即可。

衷心感谢以下 Microsoft IT 专家,感谢他们与我们分享了技术与专业知识: Gaurav Aggarwal、Anthony Bloesch、Todd Briley、Shaun Cox、Roberto Di Pietro、Michael Epprecht、Kevin Farlee、Umachandar Jayachandran、Chuck Ladd、Kaloian Manassiev、Luciano Moreira、Ward Pond、Mark Prazak、Arunachalam Thirupathi、Roger Wolter、Clement Yip 和 Frankie Yuen。

© 2008 Microsoft Corporation 与 CMP Media, LLC.保留所有权利;不得对全文或部分内容进行复制.