Howard Goldberg (howard505@gmail.com), 数据库架构师, 外企
2008 年 4 月 17 日 对于数据库来说,大量请求同样会造成“交通拥挤”,这会大大增加响应时间,让客户非常不满意。在 DB2 9.5 for Linux, Unix, and Windows 中,IBM 引入了一种先进的通信流管制机制,这种机制称为 Workload Manager(WLM),它嵌入在数据库引擎中,负责数据库工作负载的管理。 来自 IBM Database Magazine 。
设置工作负载优先级,确保首先处理最重要的工作,并保持通信流的其余部分平稳
想像一下纽约在假日出现交通阻塞的情景。如果您从来没有遇到过这种情况,那么想像一下街上有过多的汽车就行了。汽车在十字路口挤做一团,烦躁的司机们不停地按喇叭,交通完全堵塞了。在正常的交通中,在十字路口发生的一次事故会产生与波浪相似的扩散效应,造成大范围的交通迟滞。
交通信号有助于管理有限的公共道路资源,但是当交通系统遇到过大的压力时,信号系统很快就失去作用了。在繁忙的十字路口安排交通警察有助于控制汽车的通行,防止堵塞十字路口。这些交通警察提供另一级管理,保持交通顺畅,他们常常根据汽车的数量波动动态地调整其决策。
对于数据库来说,大量请求同样会造成“交通拥挤”,这会大大增加响应时间,让客户非常不满意。在 DB2 9.5 for Linux, Unix, and Windows 中,IBM 引入了一种先进的通信流管制机制,这种机制称为 Workload Manager(WLM),它嵌入在数据库引擎中。
开发 WLM 的原因
如果数据库了解关于工作负载和期望的性能的更多信息,就可以更好地使用资源。
数据库引擎按照同样的紧急程度处理所有工作请求,因为它缺少对活动进行分类和确定优先级所需的信息。尽管这个模型在大多数情况下可以正常工作,但是如果数据库掌握关于工作负载和客户(应用程序开发人员和用户)期望的性能服务水平的更多信息,就可以更好地使用它的资源。
DB2 9.5 的 WLM 对传递给数据库的所有活动进行分类,以此提高数据库的效率;它会系统化地确定工作的优先级,并按照连接识别属性和工作活动类型把性质相似的工作分组在一起。它控制和监视数据库活动和资源,利用阈值和工作操作满足服务水平协议。
当然,工作负载管理并不是新东西。在采用集中式体系结构的大型机环境中,长期使用工作负载管理帮助应用程序高效地共享资源。在大型机环境中,消耗大量资源的应用程序会对其他所有应用程序造成消极影响。在分布式平台上,过去并不认为工作负载管理是重要的,这是因为采用的是专用的资源实现方式。在使用专用实现时,使用数据库的应用程序通常拥有整个主机,所以应用程序可以自己控制对资源的使用。
但是,专用方式已经过时了。数据增长的速度越来越快,数据保持需求越来越大,客户机更频繁地并发访问数据库,数据库查询请求的复杂性也在增加。另外,内部和外部客户希望获得相同(甚至更短)的响应时间。
促使 WLM 出现的另一个因素是,事务性和决策支持工作负载集中在单一企业数据库中。事务性数据库通常支持一秒以内的响应时间,决策支持数据库通常支持更复杂更花时间的查询,但是它们之间的界限越来越模糊了。把这些工作负载集中在一起,有助于企业使用单一的整合数据库更快地做出决策。
最后一个因素是,数据中心的资产和处理能力是有限的;增加额外的容量花费很大,而且需要长期规划。WLM 可以帮助组织尽可能充分地利用现有的硬件和信息技术投资。
WLM 的构建块
构建 WLM 战略或策略与构建应用程序数据库的过程很相似。应用程序数据库是从表、索引和视图等数据库对象构建起来的,而工作负载管理战略或策略是用与 WLM 相关的数据库对象创建的。这些对象作为构建块,创建复杂全面的资源治理和监视结构。表 1 描述 WLM 构建块并按任务和范围分类。
表 1. WLM 构建块
|
数据库对象
|
任务/功能
|
范围/领域
| |
服务类
|
设置代理和预获取优先级
|
所有工作活动
| |
工作负载
|
识别连接和路由到服务类
|
连接属性
| |
工作类,工作类集,工作操作
|
按照类型识别数据库活动并应用操作
|
数据库或服务类中发生的活动(读、写、调用、装载、DML 和 DDL)
| |
阈值
|
资源控制
|
数据库或服务类中发生的所有活动
|
这些 WLM 组件帮助回答两个关键的工作负载管理问题:谁来完成这个工作,要执行什么类型的工作。WLM 引擎使用工作负载回答第一个问题,使用工作类回答第二个问题。使用阈值和工作操作执行干预操作(对工作事件做出反应,比如停止执行或把工作放到队列中)。下面详细介绍每个 WLM 构建块。
服务类。服务类定义与数据库活动相关的环境。每个服务类要么是一个服务超类,要么是服务超类中的一个服务子类。服务类控制一个代理的操作系统优先级和它的 I/O 预获取优先级,从而管理数据库活动。代理的优先级控制分配给一个服务类中运行的代理的相对操作系统优先级。这个值可以设置为默认值或特定的整数值。默认值使用操作系统分配的一般优先级;指定的整数值会要求操作系统调整代理的调度优先级。在 Unix 上,负数的代理优
先级表示代理的相对优先级更高。代理优先级的有效值范围是从 +20 到 –20。WLM 把这个数字与操作系统分配的值相加来调整优先级。I/O 预获取优先级只能设置为 high、medium 或 low。在服务类之间或使用子类的超类中设置不同的值,就可以创建多层的工作负载管理方案。
在默认情况下,预先定义了三个服务类:默认用户类(sysdefaultuserclass)、默认系统类(sysdefaultsystemclass)和默认维护类(sysdefaultmaintenanceclass)。另外,每个服务类(或超类)都包含一个默认的子类(sysdefaultsubclass)。在 DB2 系统中,所有用户请求都在默认用户类中执行,系统请求由默认系统类执行。可以把一个服务类划分为多个子类,从而对分配给这个类的工作进行更细粒度的控制。
下面的示例演示如何创建服务类:
create service class sc1 agent priority default prefetch priority high;
下面的示例演示如何创建服务子类:
create service class sc2 under sc1 agent priority default prefetch priority high;
工作负载。工作负载与一个服务类相关联,它使用连接属性识别服务类所控制的工作。
表 2. 工作负载连接属性
|
属性
|
说明/备注
| |
Applname
|
应用程序名
| |
system_user
|
系统用户名
| |
session_user
|
会话用户名
| |
session_user group
|
会话用户组
| |
session_user role
|
会话用户角色
| |
current client_userid
|
当前客户机用户 id
| |
current client_applname
|
在 9.5 中,对于命令行处理器(CLP)发起的活动,DB2 会给应用程序名加上前缀。例如,CLP create_table.ddl
| |
current client_wrkstnname
|
当前客户机工作站名
| |
current client_acctng
|
客户机连接帐户信息
|
在默认情况下,创建两个工作负载:默认用户工作负载(sysdefaultuserworkload)和默认管理工作负载(sysdefaultadmworkload)。它们都映射到用户服务类(sysdefaultuserclass)。如果不创建其他定制的工作负载,那么所有非系统工作都分配给默认用户工作负载。无论是否在数据库中启用 WLM,都采用这个配置。在连接开始时以及在工作单元的边界上,检查所有工作请求并把它们分配给一个工作负载。
创建工作负载
下面给出一个 create workload 语句的示例。它识别 session_usergroup 为 “appusers”的连接,并把它们分配给 sc1 服务类。表 2 给出可以用来识别连接的工作负载属性。
Create workload wl1 session_user group (‘appusers’) service class sc1;
工作负载连接属性。使用工作负载连接属性把工作分配给工作负载(见表 2)。每个连接属性可以包含一个或多个数据项。
客户机信息。客户机信息是通过 sqleseti API 或 wlm_set_client_info 存储过程设置的。应用程序可以使用这个存储过程向 DB2 服务器传递更多信息,帮助进行工作负载评估和报告。例如,如果数据库以前只能看到一个一般性 id,那么可以把实际客户机 id 或应用程序生成的报告 id 等补充数据从共享的应用服务器传递给数据库(表 3 给出客户机信息属性)。
表 3. 客户机信息属性
|
属性
|
说明
| |
client_userid
|
客户机的用户 id
| |
client_wrkstnname
|
客户机的工作站名
| |
client_applname
|
客户机的应用程序名
| |
client_acctstr
|
客户机的帐户字符串
| |
client_workload
|
指定工作负载分配模式。指定工作负载分配模式。sysdefaultadmworkload 值把所有工作分配给 sysdefaultadmworkload,绕开一般的工作负载分配过程。automatic 值指定应该执行一般的工作负载分配过程。
|
工作负载安全性。为了使用工作负载对象识别连接,连接 id 需要直接的使用权力,或者在组或数据库角色级设置权力。例如,可以把工作负载 wl1 的使用权力授予 appusers 组。如果在创建数据库时没有使用 restrict 选项,那么在默认情况下把 sysdefaultuserworkload 的使用权力授予 public。通过使用宽松的工作负载安全过程(比如把使用权力授予 public),客户机就可以调整连接属性并绕过工作负载安全机制,从而把它们的工作请求路由到另一个服务类。
工作类。工作负载使用连接属性(比如会话 id 和会话组 id)识别工作,而工作类根据工作的活动类型识别工作。工作类活动类型是 read、write(插入、更新、合并)、DML(read 和 write工作类型的组合)、call(存储过程)、DDL(数据定义语言命令,比如 create 和 drop)、load(可以使用工作负载属性识别的其他实用程序)和 all(所有类类型)。工作类与工作类集和工作操作一起对类类型所识别的资源进行分类、路由和控制。
工作类集。工作类集对工作类进行分组。在工作类集中,按照 create 语句或 position 子句指定的活动子句次序评估活动。例如,如果在工作类集定义中 DML 工作类的定义先于 select 工作类,那么选择活动会在 DML 工作类中评估,而不是在 select 工作类中。如果工作类或集没有相关联的工作操作,WLM 就会忽略它。
下面的示例演示如何把工作类组合为一个工作类集。“all_work_class_types”工作类集包含多个工作类,比如 read_wc(识别那些执行读活动的连接)。结合使用多个工作类和工作操作,就可以对多种活动进行控制,比如存储过程调用(call)、实用程序(load)、DDL(对象创建)或读和写(read,write)活动。
清单 1。 如何把工作类组合为一个工作类集
Create work class set all_work_class_types (work class read_wc work type read
, work class write_wc work type write
, work class ddl_wc work type ddl
, work class call_wc work type call
, work class load_wc work type load
, work class dml_wc work type dml
, work class all_wc work type all position last);
|
工作操作集。可以在数据库级或服务类级定义工作操作。如果在服务类级定义工作操作,允许的工作操作包括映射、禁止执行、收集活动数据、收集聚合的活动数据和统计活动数量。可以使用映射操作把属于指定工作类的工作请求映射(即路由)到某个服务子类。可以在数据库级执行的工作操作包括阈值识别(比如 when sqltempspace > 100MB)、禁止执行、收集活动数据和统计活动数量。阈值属性指定一个触发点,达到这个值之后,就会执行特定的工作操作。表 4 列出阈值属性。
下面的示例演示如何创建与阈值(one_query)或映射(map_dml)操作相关联的工作操作集。活动由一个工作类集(all_work_class_types)和相关联的工作类(read_wc,dml_wc)识别。
清单 2。阈值示例
create work action set database_actions for database
using work class set all_work_ class_types(work action one_query
on work class read_wc when concurrentdbcoordactivities > 1
and queuedactivities > 1 stop execution,
work action two_queries on work class write_wc
when concurrentdbcoordactivities > 2 and
queuedactivities > 2 collect activity data continue)
|
清单 3。映射示例
create work action set database_actions for service class sc1
using work class set all_work_class_types
(work action map_dml on work class dml_wc map activity to sc2)
|
注意,sc2 必须是 sc1 超类中的子类。
工作操作。工作操作不是一个独立的对象。它是工作操作集对象的组件。只能使用 DDL 命令 alter work action set 添加或修改工作操作。但是,要想改变与一个工作操作相关联的工作操作集,惟一的方法是删除并重新创建工作操作集。下面的示例说明如何在现有的工作操作集中添加一个工作操作:
清单 4。如何在现有的工作操作集中添加一个工作操作
alter work action set database_actions
add work action three_queries on work class all_wc
when concurrentdbcoordactivities > 3 and
queuedactivities > 3
stop execution;
|
阈值。阈值定义对资源的限制,以及在达到阈值时执行的后续操作。阈值可以与服务类、工作负载、工作操作或数据库中发生的任何活动相关联。可以在单一数据库分区上、跨一个 DB2 Enterprise Server Edition Data Partitioning Feature(DPF)环境中的所有数据库分区或者在工作负载级上实施阈值。在 DPF 环境中,每个跨数据库分区的工作负载会有自己的阈值边界计数器。
可以使用阈值控制以下资源:
- estimatedsqlcost(timerons)
- sqlrowsreturned
- sqltempspace(KB、MB、GB)
- activitytotaltime(天、小时或分)
- connectionidletime(天、小时或分)
- concurrentworkloadoccurrences
- concurrentdbcoordactivities 和 queuedactivities
- concurrentworkloadactivities 和 queuedactivities
- totaldbpartitionconnections 和 queuedconnections
- totalscpartitionconnections 和 queuedconnections
在达到阈值之后,可以执行以下操作:
- 收集数据,可以包括详细信息
- 停止执行
- 继续执行
- 把活动放到队列中(只适用于 concurrentdbcoordactivities 和 totalscpartitionconnections)。
表 4. 阈值属性
|
Concurrentdbcoordactivities 和 queuedactivities
| |
sqltempspace(KB,MB,GB)
| |
sqlrowsreturned
| |
estimatedsqlcost(timerons)
| |
activitytotaltime(天、小时或分)
|
表 5. 阈值类型
|
阈值类型
|
工作类/工作操作示例
|
阈值示例
| |
前瞻性
|
create work class set bad_queries_wcs (work class cost_wc work type dml
for timeroncost from 9999
to unbounded,
work class card_wc work type dml for cardinality from 1000
to unbounded)
create work action set bad_queries_was for database using work class set bad_queries_wcs
(work action bad_timeron on work class cost_wc when estimatedsqlcost > 999999 stop execution)
|
bad_queries
for service class sc1
enforcement database
when estimatedsqlcost >99999
stop execution
| |
反应性
|
create work class set bad_queries_wcs
(work class read_wc work type read)
create work action set
bad_queries_was for database using
work class set bad_read_wcs
(work action bad_read on work class read_wc when sqlrowsreturned > 999999
stop execution)
|
create threshold
bad_read_query
for service class sc1
enforcement database
when sqlrowsreturned > 999999
stop execution
|
下面的示例结合使用阈值的范围(服务类)、条件的识别(临时空间超过 100 MB)和一个阈值操作(停止执行)。可以使用 work action 命令创建相同的阈值,区别在于工作操作可以使用工作类对阈值所影响的活动的识别进行更多的控制。
清单 5。阀值使用示例
create threshold tempspace for service class sc1 enforcement database
when sqltempspace > 100 m stop execution
|
工作负载与工作类的控制范围
应该根据所需的控制级别,决定如何管理或控制数据库中发生的工作。在服务类(具有相关联的工作负载)上定义的阈值可以使用连接属性识别和管理工作。如果选择一个工作操作集和相关联的工作操作,当与工作类集和工作类结合使用时,会使用活动的类型(比如 read、write、load 和 DDL)识别工作。工作负载是粒度更细的 WLM 管理方式,允许对数据库中发生的活动乃至单独的用户进行有限的控制。工作操作方式提供更宽泛的控制级别,因为它识别活动的类型,而不考虑连接属性。但是,可以结合使用这两种方式,创建非常复杂的 WLM 战略。例如,可以使用工作负载把工作请求路由到特定的服务类,然后工作操作可以使用工作类集和操作把这些请求进一步路由到超类中的一个子类。
前瞻性阈值与反应性阈值
在 WLM 中可以设置两种类型的阈值:前瞻性阈值与反应性阈值。表 5 给出这两种阈值的示例。
前瞻性阈值在消耗资源的相关活动开始之前计算。这种阈值的示例是估计的 SQL 开销。顾名思义,这个 SQL 开销是一个估计值,可能不准确。create threshold DDL 语句只能使用 estimatedsqlcost 选项设置这个前瞻性阈值。工作类可以使用 timeroncost(与 estimatedsqlcost 相同)或 cardinality,但是只适用于 DML 类型的操作。前瞻性阈值的另一种形式是查询并发和队列。在执行查询之前,WLM 引擎可以使用 concurrentdbcoordactivities 和 queuedactivities 属性分析查询工作负载并控制并发查询的数量。
反应性阈值在工作请求开始消耗资源之后计算。反应性的指标比前瞻性指标多得多。
从简单的开始
可以使用 WLM 识别和研究数据库的活动模式。了解了这些模式之后,就可以创建 WLM 策略,尽可能提高数据库环境的效率。这是一个迭代式的过程,可能需要多次调整。
参考资源
关于作者  | |  | Howard Goldberg[howard505@gmail.com] 在数据库技术和数据仓库方面具有超过 25 年的经验。他当前在一家大型金融服务公司担任数据库架构师,负责用 DB2 实现大型任务关键数据仓库。 |
对本文的评价
|