前言
本书主要面向Microsoft SQL Server各个版本的数据库系统管理和开发人员,介绍SQL Server关系型数据库引擎在日常使用和开发过程中经常会遇到的问题、其表现形式、背后运行机理、基本理论知识、搜集和分析问题日志的方法,以及解决实际问题的可选手段。本书的最大特点是面向实战。讨论的主题都是在企业开发数据库应用和使用SQL Server过程中,常见的经典的问题。而里面包含的案例分析,都来源于真实案例。阅读本书可以帮助数据库管理与开发人员更深入地理解SQL Server的原理和运行规律,以提高解决问题的能力。
本书的缘起
从1999年作者开始支持Microsoft SQL Server以来,不觉10年过去了。作为一个数据库支持工程师,每天都能接触到各式各样的SQL Server问题。而在微软内部,又有大量的技术资料,有机会进行一些比较系统的学习,所以成长环境还是很优越的。这么些年和SQL Server打交道,对这个产品渐渐产生了感情。可以说,我个人是随着产品成长起来的。SQL Server作为微软比较成熟的产品,在过去的10年里有了长足的进步。
在日常工作中,除了支持不同的客户以外,也要对自己所学进行总结,以便传承知识。所以开始搜集一些有意义的问题。一半是个人兴趣,一半也是技术总结的需要。对新工程师,通过案例分析学习效果很好。所以我积累了一些比较有代表性问题的小结和案例。
在SQL Server的各类问题里,作者个人最感兴趣的是性能调优的问题。而这部分需求随着SQL Server在企业级平台上日益广泛的使用,渐渐突出起来。微软的SQL Server技术支持部门,总结了一套系统的分析和解决问题的方法。现在很多白皮书、Blog都有所介绍,但是完整地介绍这套方法的资料非常有限,而有分析案例的资源就更少。
在支持SQL Server用户的时候,一个很深刻的体会,是大家对SQL Server的能力信心普遍不足。很多用户还把SQL Server当中小型数据库管理系统理解和使用。当系统出现各种问题的时候,将其归结为SQL Server能力有限。很多人在指责SQL Server的时候,本身对SQL Server的理解并不是那么深入。作为一个对SQL Server有感情的从业人员,作者常常感到惋惜和遗憾。
SQL Server的确不是万能的,在有些地方,它的确有自己的局限和不足。但是,这并不妨碍SQL Server支持大数据量、大并发用户数、高负荷的企业级应用。作者曾经为客户做过压力测试,在一台并不十分强劲的服务器上运行SQL Server,前端同时支持十几台Web服务器,而每台Web服务器又同时模仿大量用户做压力测试。最大的压力下,这些Web服务器的CPU使用率已经达到100%,几乎没有响应了,但是SQL Server还运行得好好的,响应速度还不错。随着64位机器的普及和SQL Server 2005& 2008的更广泛使用,SQL Server的能力又提高了一个台阶。作者个人见过很多同时支持超过2000个SQL Server并发用户,每秒钟处理超过3000个Batch(批处理)请求的SQL Server。SQL Server本身的能力,对大部分的应用场景来讲应该算是合格的。
可是在现实使用里,很多SQL Server应用远远没有达到上面的能力。每秒钟处理几百个,甚至只有几十个批处理请求,就已经无法支撑。这和数据库设计、应用设计、以及日常管理都有关系。虽然SQL Server可以被当作傻瓜机使用,但是如果要完全发挥SQL Server的能力,还是需要了解其工作原理、设计和配置方法,以及掌握分析和解决不同类型问题的能力。有些地方对开发者和数据库管理员的技术要求,并不比其他企业级数据库低。作为一个支持工程师,作者学会了很多方法和技巧。可是在和用户的沟通过程中,发现掌握这些方法的人并不是很多。有些人对某些方法,还有一些误解。
在博文视点的几位老师的鼓励和支持下,作者把自己掌握的,有关关系型数据库引擎的知识作了一些梳理,总结出在SQL Server设计和管理过程中最常遇到的问题,进行了比较完整的阐述。这些知识来自于对很多技术文档、白皮书、联机丛书和Blog的学习,也来自于处理真实问题过程中产生的感悟。在介绍一些基本概念的时候,联机文档里的定义和说明是最权威的,所以我有意识地引用了一些,而不是自己写。有时候觉得联机丛书里的中文表达不太贴切,会加一些自己的理解。作者的一个小小希望,是通过这本书,能够对业界更顺利地使用SQL Server,起一点的推动作用。
本书的结构
本书主要分为两大部分。第一部分包括第1章到第5章,主要是谈SQL Server服务和数据库在使用过程中,比较容易遇到的问题,包括空间管理,数据库备份和恢复手段,SQL Server服务或数据库不可访问,数据库损坏修复与预防,连接和认证等问题。
第二部分包括第6章到第13章,主要是谈论SQL Server在运行过程中对各种资源的使用,以及由此可能会遇到的服务器不稳定、或者是性能问题。
最后第14章是个工具性章节,总结了处理SQL Server问题时可能需要检查的日志种类,以及搜集它们的方法。在读者阅读前面各章的时候,都可以做参考。
下面是各个章节内容的粗略介绍,以及它们之间内涵的逻辑关系。
第一部分讲的是SQL Server服务和数据库在使用过程中,比较容易遇到的问题。
第1章:数据库空间管理
在数据库里存储数据,是SQL Server存在的理由。管理员的一个比较头痛的问题,是数据库的数据文件或者日志文件,出人意料地增长。本书先从单个数据库谈起,从数据的存储方式,数据库空间检查方法入手,介绍文件空间是如何被SQL Server使用掉的。然后,会对数据文件和日志文件使用方式作深入分析,从而解决数据文件无法收缩或清空,以及日志文件无限增长的问题。最后,会讨论数据库自动增长与自动收缩设置的利弊。利用这一章的知识,管理员将可以比较自如地分析数据库空间使用,并采取适当的方法合理使用数据库文件空间。
第2章:数据库备份与恢复
把数据存储在数据库里以后,数据库管理员就有责任保护它们的安全。数据库备份是管理员的重要职责。而在灾难发生后能够根据现有的备份,用最短的时间恢复数据库,也是管理员面临的挑战。本章将介绍SQL Server提供的各种备份和恢复手段,以及它们最适合使用的时机。本章还会介绍用户数据库和系统数据库备份与恢复所要注意的不同要点。最后,有一个练习,详细展示了将数据库系统完全通过备份和恢复的方法,迁移到另一台服务器的具体步骤。
第3章:SQL Server服务或数据库不可访问
只有在SQL Server服务和每个数据库正常启动以后,用户才能访问他需要使用的数据库里的数据。本章将按照SQL Server服务启动的顺序,分析它在启动过程中的每一步可能会遇到的问题,以及这些问题的解决方法。通过这一章的介绍,读者将可以对大部分的SQL Server服务不可用问题有所认识,从而能够自己去解决问题。本章还会介绍系统数据库和用户数据库不能正常打开的原因,以及解决不同类型问题的方法。通过这些方法的介绍,管理员可以修复部分不能正常打开,但是还没有彻底损坏的数据库。
第4章:数据库损坏修复
数据库物理损坏对SQL Server的正常使用是一个严重的威胁。轻则单条数据记录访问失败,原先存储进去的数据无法取出,重则可能导致整个数据库无法启动,更严重时甚至可能影响到SQL Server的正常运行,导致整个SQL Server系统的崩溃。本章会介绍数据库会发生什么样的损坏,以使得读者能对所谓“数据库损坏”这个概念有直观的认识。然后会介绍数据库损坏检测与修复指令:DBCC CHECKDB。在有些系统里,会发生数据库反复损坏的问题,这无疑是数据库管理员的梦魇。本章会介绍发生这种问题时,数据库管理员可以采用哪些经验方法,怎样能够尽快定位到问题的原因。
第5章:连接与认证
SQL Server服务和数据库都准备好以后,用户就可以访问了。每个用户访问到数据之前,都要成功建立连接,并且通过身份认证。本章会介绍SQL Server支持的网络协议,以及客户端连接是怎么选择使用哪个网络协议的。本章还会介绍常用的两个协议TCP/IP和Named Pipe在连接失败时的检测步骤,以及General Network Error(GNE)错误可能产生的原因、避免这个错误的最佳实践。最后,我们还会介绍SQL Server支持的两个认证模式:SQL Authentication和Windows Authentication,以及SQL Server什么时候会使用Windows Delegation,这样的SQL Server需要做什么特别配置。
第二部分讲的是资源使用与性能问题。
SQL Server的性能问题主要有三大类:(1)系统资源瓶颈;(2)SQL Server内部阻塞或者其他资源等待;(3)不够优化的设计或者过分复杂的语句。而系统资源瓶颈,又分内存、磁盘I/O,以及CPU这三大类。本书的章节,也是根据这个顺序展开的。
资源不足时,可能出现性能问题,但严重时也可能会导致SQL Server服务器不能正常工作,甚至不响应。所以,各个章节里涵盖了一些和资源使用相关的SQL Server系统错误,或者是Server Hang(服务不响应)问题。当我们确认SQL Server系统运行健康以后,才会进一步检查性能问题。
第6章:SQL Server内存分配理念和常见内存问题
内存资源是SQL Server最重要的系统资源。本章将从Windows内存分配开始讲起,先了解SQL Server内存使用和Windows之间的关系。然后解读SQL Server独特的内存管理模式,了解SQL Server内部的内存有哪些用途。按照这些用途分类,分析SQL Server每个部分的内存使用量,各个部分内存遇到压力时的表现,以及应对方法。针对不同类型的问题和错误,会有典型的案例分析。本章还会分析一些对于SQL Server内存使用的常见误解,澄清一些错误的认识。这一章里理论知识比较多,可能比较艰深。但的确是保障SQL Server健康运行和性能调优的一个很重要的环节。
第7章:SQL Server I/O问题
I/O瓶颈也是SQL Server经常遇到的一个问题。本章会介绍SQL Server在做什么操作时候,怎么样和硬盘做读写交互。当遇到I/O问题的时候,如果不能很容易地提高硬盘的响应速度,减少SQL Server发出的读写请求可能是个更好的方案。本章会介绍在Windows层面和SQL Server层面,怎么分析和界定I/O问题。最后会介绍一个微软提供的硬盘压力测试工具。通过它,可以在服务器投入使用之前测试硬盘运行速度的快慢。
第8章:任务调度与CPU问题
这里会谈到两类问题。第一类是SQL Server的任务调度出现问题,服务不能正常响应。本章将详细介绍SQL Server的任务调度机制,以及出现的警告信息意味着什么,怎么做初步问题定位。另一类是SQL Server服务CPU使用率很高,进而影响整体性能,但是任务调度没有出问题。像定位内存和I/O问题一样,管理员也可以通过分析SQL Server的各项日志信息,定位造成SQL Server处理器使用量高的原因。一般来说,最后都要定位到几个或者一批语句,优化这些语句的设计,或者降低系统负载。
第9章和第10章:阻塞与死锁
有事务就会有锁,有锁就会有阻塞和死锁。阻塞与死锁是SQL Server系统里非常常见的现象。
在第9章里,主要侧重于背景知识的介绍,让读者了解锁的来源,其模式、兼容性,在做Select、 Updat、, Delete、 Insert这些动作时,锁是什么时候申请的,在不同的表结构上会申请多少锁资源,又会在什么时候被释放。本章还会介绍监视锁的申请、持有和释放过程的方法。有了这些知识准备,才能去有效地分析和解决阻塞与死锁问题。本章还介绍了SQL Server 2005引入的基于行版本控制的隔离级别,以及它为什么会在有些情况下缓解阻塞与死锁。
在第10章里,主要侧重于具体问题的解决。作为DBA的一个基本功,本章会展示如何定位一个正在发生的阻塞问题。接着讨论了常见的阻塞原因以及它们的解决办法。本章还会以连接池为案例,展示阻塞的出现和应用程序行为之间的紧密关系,因为消除阻塞经常是需要修改应用程序设计的。最后,还会介绍死锁问题的定位和解决方法。这里的案例分析,展示了数据库设计对阻塞和死锁类问题的影响。
第11章:从等待状态判断系统资源瓶颈
SQL Server里有一系列系统视图,可以了解每一个用户连接当前的运行状态。如果连接运行因为缺少某种资源而进入暂时等待状态,视图里也会显示出在等什么资源,包括内存、磁盘I/O、CPU,和锁资源等等。在从第6章到第10章介绍过主要的资源使用以后,本章作为一个总结性章节,介绍了在系统视图里可能会看见的各种等待,它们产生的原因以及可能的解决办法。在实际操作中,往往可以直接跳到这一步,先大致确定资源瓶颈是哪一个,然后再用前面相关章节介绍的方法做进一步的确认和分析。
第12章和第13章:语句调优
当问题界定到是因为一句语句运行时间过长,或者申请资源太多,那就要做语句层面的调优了。
在第12章里,主要侧重于背景知识的介绍。SQL Server需要索引帮助来检索数据,也需要统计信息来帮助它选取合适的执行计划。本章会介绍不同类型的索引如何帮助数据检索,统计信息的读取、维护和更新。执行计划生成的过程叫编译。本章会介绍编译,执行计划重用,重编译,以及它们对语句执行的影响。语句调优的另一个基本功,是要能够读懂执行计划,懂得语句运行的统计信息。知道这些,才能找到语句的问题在哪儿。这些本章也会有所介绍。
第13章是比较长的一章。语句运行得不够快,可能是因为做了物理I/O,也可能是因为编译速度影响。排除这两种可能以后,就要确认语句的执行计划是否合适。可能是SQL Server错误地预估了cost,选择了不正确的算法,也可能是因为重用了一个对自己不合适的执行计划。如果确认了SQL Server已经选择了一个比较正确的执行计划,但是执行时间还是不够快,那就要考虑调整数据库设计,调整索引,或者配置执行计划指南,以增进运行速度。另一条思路,是调整语句设计,用更优化的方法实现同样的逻辑。这常常会大大提高执行的效率。
第14章:常用SQL Server系统信息与搜集方法
作为一个可支持性比较好的软件,SQL Server提供了很多方法收集系统信息,包括Windows Event Log, SQL errorlog, 性能监视器,系统管理视图等等。可供分析的信息非常丰富,但是也要管理员能够充分利用。所以作为一个比较独立的章节,这里总结了管理员可能会使用到的大部分信息收集方法,供读者参考。这些方法里有手工收集的,也有自动收集的。读者可以在自己的SQL Server上试一试,选择和练习一些你喜欢的方法,以备不时之需。
本书基于的版本
SQL Server 2000是个比较成熟的版本,在业界被广泛使用。SQL Server 2005在SQL Server 2000的基础上,作了一些重要的扩充和增强。例如,增加了Partition Table,动态管理视图这一类用户经常使用得到的功能,而且用户界面也有了很大变化。从高端使用看,SQL Server 2005有其固有的优势,现在使用得也比较广泛起来。SQL Server 2008在SQL Server 2005的基础上又作了进一步改进,但是在用户界面以及管理方法上,变化没有SQL Server 2000到SQL Server 2005这么大。
本书讨论的问题,绝大部分对各个版本都能适用,只是有些细节可能会有所不同,新版本可能会有些新做法。所以本书主要基于SQL Server 2005版。而对SQL Server 2008的更新功能,也会提到。
本书不包含的内容
本书主要关注与关系型数据库引擎的管理和使用,对SQL Server的一些其他组件,例如,Cluster,Replication,Database Mirroring,Log Shipping等都没有谈及。对于SQL Server的Business Intelligence组件部分,例如SQL Server Analysis Service,SQL Server Reporting Service,SQL Server Intelligence Service等,也没有涉及。
本书的范例脚本
本书的各个章节里,都有很多范例脚本,或者是测试脚本。为了帮助读者做测试,我们把这些脚本另外保存在一些文件里,放在http://download.csdn.net/source/1992551下,供读者下载。