|
知识路径: > 测试技术的分类 > 应用负载压力测试 > 负载压力测试实施 > 结果评估与测试报告 >
|
考试要求:掌握
相关知识点:21个
|
|
|
|
数据库服务器性能问题主要表现在某些类型操作的响应时间过长、同一类型事务的并发处理能力差和锁冲突频繁发生等方面。应该说,这些问题是数据库服务器性能不佳的典型表现。由于造成上述情况的原因众多,需要分情况加以分析。
|
|
|
|
响应时间(Response Time, RT)是系统完成事务执行准备后所采集的时间戳和系统完成待执行事务后所采集的时间戳之间的时间间隔,是衡量特定类型应用事务性能的重要指标,标志了用户执行一项操作大致需要多长时间。响应时间过长意味着用户完成执行一项命令需要等待相当长的时间。实践表明,通常情况下用户能够接受的响应时间最大为200 ms。不仅如此,响应时间过长也是造成系统锁冲突严重的重要原因之一。
|
|
|
造成响应时间过长的原因非常复杂,通常可以从以下几个方面考虑。
|
|
|
|
|
|
|
|
数据库服务器负载过重不可避免地会造成响应时间过长。这标志着当前服务器系统的硬件条件不能满足实际用户对性能的需要。服务器负载过重主要表现在CPU使用率高、内存占用率大、I/O与页面交换频繁发生等方面。由于服务器系统本身一般都提供性能监控程序,定位服务器性能问题相对比较容易。解决这类问题的方法一般是升级服务器硬件,提高数据库服务器本身的处理能力。但是,通过升级服务器硬件获得的性能提升是很有限的,并且对于某些诸如算法复杂度过高等问题根本无法解决。
|
|
|
|
糟糕的数据库设计是导致单一事务响应时间过长的最重要原因。通常,数据库设计在系统开发初期进行,此时,数据库设计人员往往对数据的实际规模和特性没有足够的了解。在数据库设计方面,对响应时间影响较大的因素有数据库表的规模、索引的使用、数据的分布、查询优化等。其中索引的使用极大影响事务执行的响应时间。实际上,很多情况下应用程序在访问大规模数据库表时的确没有使用索引。造成这种情况的原因通常是开发人员的疏忽,也有用户的需求变化过多,某些数据库字段不适合建立索引的情况。在这里需要特别指出的是,对组合索引进行查询时,查询条件中字段的顺序与数据库设计的索引字段顺序要一致。如果顺序颠倒,组合索引根本不能被数据库使用。例如,表A(field1, field2, field3),有组合索引index(field1, field2),诸如
|
|
|
SELECT * FROM A WHERE((field2=condition2)AND(field1=condition1))和SELECT * FROM A WHERE(field2=condition2)的查询无法使用index索引。此外,并非增加索引就一定能够提高单一事务执行的响应时间。过多的索引使用将极大地增加插入操作(INSERT)的花费,从而使响应时间变长。
|
|
|
数据库表规模过大,是指单一数据库表的记录数在百万行以上,对这类表直接进行检索而不采取必要的优化手段,必然造成单一查询响应时间过长。如果数据库表的规模一再增大,使用索引也不能很有效地解决响应时间过长的问题。对此类问题,可能的解决办法是对数据进行分布,使查询能够并行执行或缩小查询的范围。目前,主流关系数据库管理系统都提供表分区(分段)存储,以使得软件开发人员比较容易地实现数据分布。
|
|
|
查询优化对响应时间的影响也不容忽视,尽管优化活动由数据库管理系统完成。实际上一条结构化查询语句(SQL)的写法有很多种,不同的写法可能有不同的响应时间,这一差别可能非常大。如果开发人员在软件编写过程中恰好使用了执行效率低的SQL语句,其响应时间自然就会变长。目前,某些独立软件开发商已经注意到这种情况,并开发了相应的软件帮助应用软件开发人员找到执行最快的SQL语句的写法。但是,由于数据库本身是动态变化的,执行最快的SQL语句也可能变化,所以这种方法也是有局限性的。
|
|
|
|
事务粒度过大指单一数据库事务执行过程中,需要以某种并发控制机制访问多个数据库资源。通常采用的并发控制机制是互斥锁或者共享锁。这种大粒度事务的执行由于要访问多个数据库资源(如数据库表),本身就需要消耗相当长的时间。此外,由于通常事务在执行的时候会对数据库资源进行加锁,这类事务也对其他访问该资源的用户造成影响。由于这类事务通常使用的锁数量都在两个以上,如果不合理地进行控制,极容易造成死锁。因此,在应用软件设计过程中,应该尽量消除大粒度事务。
|
|
|
|
批任务是指一次操作将对数据库中大量数据进行互斥访问的数据库事务。这种类型的事务通常将更新同一个数据库表中的数千项乃至更多的数据。由于这类任务把所有操作放置在同一个数据库事务中,所访问的资源在其执行过程中始终被锁定,必然会对其他普通事务造成访问影响。此外,由于这类任务本身将对数据库服务器造成巨大的负担,使得服务器负载加重,从而影响独立事务的响应时间。通常情况下,批任务推荐在系统具有较长空闲时完成(如晚上),这样可以保证不对独立事务造成影响。如果由于业务的要求,批任务必须与独立事务混合运行,则必须对其加以改造,以减轻对其他事务的影响。
|
|
|
|
并发处理能力差是指应用系统在执行同一类型事务的多个实例时,不能获得与执行实例数量相当的吞吐量,而是大大低于理论值。一般来说,这类问题都是由于互斥访问造成的,即并发执行中的某个实例以互斥方式对资源进行访问,造成了其他同类型用户必需等待该实例释放锁定资源后才能执行。应该指出,由于某些资源必须以互斥的方式进行访问,某些类型的事务在同一时间是只能有一个进行执行的。对于并发处理能力差的问题,可能的解决方法有,降低同一类型事务中锁的粒度、优化应用逻辑以缩短单一类型事务响应时间等。
|
|
|
|
锁冲突是每个以关系数据库为核心的信息系统必须解决的问题。这里的锁冲突是指同一类型或不同类型事务在并发执行的情况下,由于资源互斥而相互影响,造成一个或多个事务无法正常执行的情况,包括资源锁定造成的数据库事务超时和死锁两个方面。
|
|
|
|
资源锁定导致的数据库事务超时,其原因是多方面的,其中,批任务影响其他类型独立事务的情况占有相当大的比重。此外,某些改造过的批任务由于频繁对特定资源进行锁定,也会对独立事务造成相当大的影响。如果在设定时间内,数据库服务器由于资源锁定没有能够完成客户端发出的操作请求,数据库服务器将通知被锁定的客户端该操作超时。
|
|
|
某些大粒度事务在并发执行的实例较多时也会造成同类或不同事务的数据库超时。
|
|
|
此外,应用系统如果没有健壮的异常处理机制,很可能造成锁资源不被释放(即,开始的事务既没有提交也没有回滚)。当这种错误发生时,必然造成资源被长久锁定。对此类问题,应用系统在开发的过程中需要采取一套完善的异常处理机制,确保资源不被长期锁定。
|
|
|
|
由于数据库死锁可以看作进程间死锁的一种特殊情况,我们可以采取与处理操作系统死锁相类似的方法解决数据库死锁的问题。造成死锁必须具备下述条件(Coffman et al 1971):
|
|
|
①互斥条件。每一个资源或者被分配给特定的进程,或者可用。
|
|
|
②持有并等待条件。被授权持有资源较早的进程可以请求新的资源。
|
|
|
③不可取代原则。事先被赋予的资源不能够从该进程被强制取走,它们必须被所持有的进程明确释放。
|
|
|
④环等待条件。必须存在两个或者多个进程的环形链,其中每一进程都等待由环形链的下一个成员所持有的资源。
|
|
|
由于软件开发人员对资源争用可能造成的死锁问题往往没有充分考虑,而目前主流数据库管理系统主要采用乐观的并发控制算法,导致应用系统实际使用过程中频繁发生死锁。应该说明,同类型数据库事务的不同实例之间由于访问资源的顺序一致,通常情况不会发生死锁;不同类型事务之间如果没有按照一个统一的契约进行并发访问,将极容易形成死锁。因此,在确保应用系统功能的前提下,制定一个不同事务之间进行并发访问的原则,就可以有效消除环等待,减少死锁发生的可能性。
|
|
|
针对数据库的性能问题,一般应采用什么样的解决办法呢?
|
|
|
在对数据库服务器常见性能问题进行充分研究的基础上,我们制定了一套适用于解决已发布系统性能问题的通用方法,步骤如下:
|
|
|
|
|
|
④对规模较大的数据或者无法通过一般优化解决的锁冲突进行分布。
|
|
|
必须指出,解决数据库性能问题是一个迭代和往复的过程,通常需要在各种条件的矛盾之间寻求最佳的平衡点。
|
|
|
|
对数据库服务器软件、操作系统、网络环境乃至客户端等各类处理单元的性能相关信息进行监视并记录,是发现数据库性能问题的基础。这一步骤的作用是搜集与数据库服务器性能表现密切相关的数据,作为分析性能问题的基础。由于各个处理单元的状态是随着时间的推移而动态变化的,性能数据的监视与采集必须尽可能详细地记录下所有时间点上各个处理单元的状态信息。为此,我们采取对各个采样时间点的处理单元状态信息进行快照方式,来对性能相关数据进行监控和记录,相邻采样时间点之间的间隔越小,状态信息就越准确。
|
|
|
在各类监视活动中,对数据库服务器软件性能属性的监视是整个活动的重点,主要集中在数据库会话的状态信息、执行的结构化查询语句和锁使用情况等方面。其中,状态信息代表了单一数据库会话在其生命周期中的状态变化情况,包括在哪一个时间点开始一个事务,在哪一个时间点被其他会话锁定,何时超时等。执行的结构化查询语句代表单一数据库会话在其生命周期中执行的所有数据库操作。锁使用情况代表整个数据库服务器的锁资源使用和变化情况。此外,顺序扫描、高代价查询等属性也是代表数据库服务器性能的重要数据。
|
|
|
|
通过对数据库锁使用情况和SQL语句的执行历史进行分析,可以发现一个事务同时占用大量数据库锁的应用逻辑事务。通常这类事务都属于批任务。由于批任务本身的特性,决定了在其整个执行过程中,必然消耗大量资源,最好将其放置在系统具有充分空闲时间时进行。
|
|
|
|
如果应用系统锁冲突频繁发生,那么该系统的性能表现不可能令人满意。导致这种问题的原因非常复杂,主要表现在事务粒度过大、响应时间过长、异类事务互相影响并形成死锁等情况。通过对数据库锁使用情况信息的分析,可以定位发生锁冲突的各个会话;在此基础上对发生锁冲突的会话各自的执行状态变化和结构化查询语句进行分析,可以定位发生锁冲突的应用逻辑源程序。如果造成锁冲突的是同种或者异种普通事务,必须对其本身特性加以分析,确定是否本身粒度过大,数据访问是否存在瓶颈等。对这类事务的优化相对较难,一般需要开发人员的经验和对应用逻辑本身特性的了解。
|
|
|
|
数据分布的主要目的是,通过数据库服务器的并行执行特性,使得单一事务的执行具有较短的响应时间和不同类的事务之间影响相对缩小。在缩短响应时间方面,这种方法主要适用于对规模较大的数据库表进行访问的情况。它不仅使得特定的查询可以并行执行,而且有可能改变结构化查询语句的执行计划,缩小查询进行的范围。此外对于异类事务之间,或者同类事务的不同实例锁冲突频繁的问题,可以通过数据分布加以解决。
|
|
|
数据库性能问题通常表现在响应时间过长,并发处理能力差和锁冲突严重等方面,其原因是多方面的。本书提出的通过监视并记录应用系统处理单元性能相关数据,来定位性能问题的方法,可以帮助开发人员有效发现系统中存在的主要性能问题。必须指出,解决数据库性能问题是一个迭代和往复的过程,通常需要在各种条件的矛盾之间寻求合理的平衡点。
|
|
|