像SQL Server这样的数据库管理系统依赖于文件输入/输出操作的及时进行。有故障或配置不当的硬件、固件设置、筛选器驱动程序、压缩、程序错误以及I/O路径内的其他情况都可能导致阻塞或延迟I/O问题,并且很快对SQL Server性能产生消极影响。
上述问题对SQL Server的影响因问题细节的不同而差异很大,但它们通常导致阻塞、锁存器争用和超时、过长的响应时间以及资源的过度利用。
阻塞I/O是指必须进行外部干预才能完成的I/O请求(通常是I/O请求包(IRP))。这种状况通常需要执行完整的系统重新启动或类似操作才能解决,并且强烈表明硬件有故障或者在I/O路径组件中存在程序错误。
延迟I/O是指无需干预即可完成但所花时间超过预期时间的I/O请求(同样,这通常是IRP)。这种状况的原因通常是硬件配置、固件设置或筛选器驱动程序干预,需要硬件或软件供应商提供帮助以便跟踪和解决。
SQL Server 2000 SP4 包含数据库和日志文件I/O(读和写)逻辑以便检测延迟和阻塞状况。当I/O操作经过15秒钟或更长时间仍未完成时,SQL Server 会检测到并报告这一状况。以下消息将被记录到SQL Server 错误日志中:
2004-11-11 00:21:25.26 spid1 SQL Serverhas encountered 192
occurrence(s) of IO requests taking longer than 15 seconds to complete
on file [E:SEDATAstressdb5.ndf] in database [stressdb] (7). The OS
file handle is 0x00000000000074D4. The offset of the latest long IO is:
x00000000022000".
该消息表明,当前工作负载需求超出了I/O路径或当前系统配置和功能,或者I/O 路径含有不能正常工作的软件(固件、驱动程序)或硬件组件。
所记录的错误信息提供了以下信息:
• ### occurrences — 未能在15秒钟以内完成读或写操作的I/O请求的数量。
• File information — 完整的文件名、数据库名和受影响文件的DBID。
• File handle — 该文件的操作系统句柄。可以通过调试器和其他实用工具来使用这一信息跟踪IRP请求。
• Offset — 上一个阻塞或延迟I/O的偏移量。可以通过调试器和其他实用工具来使用这一信息跟踪IRP请求。(注:在记录该消息的时候,该I/O可能不再阻塞或延迟。)
记录与报告
I/O的报告和记录是按照文件执行的。延迟和阻塞I/O请求的检测和报告是两个不同的操作。
检测(记录)是在SQL Server内部的两个位置处理的。第一个位置是在I/O实际完成的时候。如果请求花费了15秒钟以上,则发生记录操作。第二个位置是在延迟写入器进程执行的时候。当延迟写入器执行时,它包含新的对所有挂起的数据和日志文件I/O请求进行检查的操作,并且,如果已经超过了15秒钟的阈值,则会发生记录操作。
报告是按照不低于5分钟的时间间隔执行的。当对文件进行下一次I/O请求时,发生报告操作。如果记录操作已经发生,并且自上一次报告发生以来已经过去了5分钟或更长时间,则向错误日志中写入新的报告(上面显示的错误消息)。
15 秒钟的阈值当前是不可调整的。尽管不推荐这样做,但您可以用跟踪标志830完全禁用延迟和阻塞I/O检测。在SQL Server启动期间设置启动参数–T830可以禁用延迟/阻塞I/O检测。使用dbcc traceon(830, -1)可以禁用对当前正在运行的SQL Server实例的检测。只有重新启动SQL Server,Dbcc traceon才会生效。
注:延迟或阻塞的给定I/O请求只会报告一次。如果消息报告10个I/O被延迟,则这10个报告不会再次发生。如果下一个消息报告15个I/O被阻塞,则表明15个新的I/O请求已经被延迟。
性能和计划操作
总体系统性能可能在I/O处理中扮演关键的角色。在研究延迟或阻塞I/O的报告时,应该考虑系统的综合运行状况。过多的负载可能导致整个系统(包括I/O处理)变慢。系统在发生问题时的行为可能是确定问题根源的关键所在。例如,如果CPU利用率在发生问题时变高或者保持较高水平,则可能表明系统中的某个进程正在消耗如此之多的CPU时间,以至于它以各种方式对其他进程产生了消极影响。
请查看性能计数器Average Disk Sec/Transfer以及Average Disk Queue Length或Current Disk Queue Length,以获得特定的 I/O 路径信息。例如,SQL Server计算机上的Average Disk Sec/Transfer通常低于15ms。如果该值上升,则可能表明I/O 子系统无法满足I/O要求。
请记住,SQL Server充分利用了Windows的异步I/O功能,并且猛烈地扩展磁盘队列长度,因此上述性能计数器具有较高的值本身并不表明存在问题。
索引和并行性
特别常见的一种情况是,因为索引丢失以及由此导致的扫描、哈希和排序对I/O系统造成的压力,所以突发大量的 I/O。运行一遍“Index Turning Wizard”通常会有助于解决系统的I/O压力。如果添加索引可以帮助查询避免表扫描甚至排序或哈希,则系统可以获得多个优点:
• 减少完成操作所需的物理 I/O,这直接等效于提高查询的性能。
• 数据缓存中只有较少的页面必须周转,因此缓存中的那些页面可以一直与活动查询相关。
• 避免不必要的排序和哈希。
• 可以降低tempdb利用率和减少争用情况。
• 减少资源利用率和/或并行操作。因为SQL Server不能保证服务器在确定是否将查询并行化时考虑并行查询执行和系统中的负载,所以您最好针对串行执行优化所有查询。在Q/A环境中,应该将max degree of parallelism设置为1,以便对根本没有从服务器收到任何并行计划的最糟糕情况强行进行调整。如果在测试环境中证实查询可以按串行方式高效执行,则生产环境中的并行计划可以提供出乎意料的性能改进。但是,很多情况下,SQL Server 选择并行执行,这是因为要遍历数据的绝对数量过于庞大。该数据量通常直接受到索引的影响。例如,如果丢失索引,则可能产生大量排序操作。我们很容易就可以看出,执行排序操作的多个辅助进程如何使响应速度比以串行方式处理排序更快速,不过我们需要了解,该操作可能大幅增加I/O系统的压力。当多个辅助进程并发运行时,来自多个辅助进程的大型读请求可能导致I/O突发以及CPU利用率提高。很多时候,如果添加了索引或者发生了其他调整操作,则可以调整查询以使其更快地运行并使用更少的资源。这不仅提高了相关查询的性能,而且还提高了系统的整体性能。