在一些大型系統當中,有時我們會考慮對系統資源和負載進行管理。DB2 V9.5 當中提供了一個全新的工具 Workload management(WLM),而 DB2 的 WLM 的功能卻缺少了一個重要的一點,對 CPU 資源進行限制,而這一點在實際的案例當中往往是受到重視的。可見僅僅是 DB2 的工作負載管理( WLM )功能還無法給客戶在這方面一個完整的解決方案。而這篇文章主要是通過實踐告訴讀者,在實際場景當中我們能夠如何結合 DB2 與 AIX 操作系統的 WLM 給出一個完整的解決方案,並希望以此帶給讀者一個真正入門的台階。
DB2 Workload Management
DB2 在資源負載管理方面,過去我們有 Governor 和 Query Patroller(QP),在 DB2 9.5 版本當中推出了工作負載管理 (Workload Management) 這個工具,以整合和替代過去的功能。由於本文重點在於實踐,對於 DB2 WLM 的基本功能和相關概念就不再闡述。所以也希望讀者在通讀本文之前對於 DB2 WLM 的基本概念有一定的認識,如果讀者想要補充學習 DB2 WLM 的基礎知識可參考 DeveloperWorks 中 《DB2 V9.5 工作負載管理》一文。
在實際的場景當中,如果要確定一個方案,我們很關心 DB2 WLM 到底能夠針對哪些資源,或者說是哪些對象進行管理和限制。我們這裡簡要列舉一下 DB2 WLM 可以使用的閥值 (Threshold):
estimatedsqlcost(timerons)
sqlrowsreturned
sqltempspace(KB、MB、GB)
activitytotaltime(天、小時或分)
connectionidletime(天、小時或分)
concurrentworkloadoccurrences
concurrentdbcoordactivities | and queuedactivitIEs
concurrentworkloadactivities | and queuedactivitIEs
totaldbpartitionconnections | and queuedconnections
totalscpartitionconnections | and queuedconnections
這裡我們可以看到 DB2 WLM 的閥值當中沒有操作系統資源的相關內容。當然我們可以在創建 Service Class 的時候指定代理程序的優先級。可是優先級往往不是客戶所需要的,而且我們有理由相信 10 個最低優先級的代理程序是能夠比 1 個高優先級的代理程序獲得更多的資源,也就是說無法通過優先級來確切地保證某些應用或者用戶不會使用超過給定量的資源。
在實際場景當中,我們常常會想到,我要限制某個次要應用用戶的 CPU 資源的使用率在 10% 以下,以免影響主營業務應用的高效運作。或者說某個系統有 3 個應用,我們根據這這 3 個應用的負載特征和重要程度定義 application1 占用 50%CPU 資源,application2 使用 30%CPU 資源,application3 使用 20% 的 CPU 資源。類似的需求還是很常見的,那麼這裡我們就需要用到 AIX 的 WLM 來實現。既然要用 AIX WLM,就得先來補充點相關的知識。
AIX Workload manager
AIX WLM 主要是對操作系統的 CPU、物理內存和 I/O 資源進行管理,我們可以設定相關資源的最大值、最小值或者按照百分比進行分配。AIX WLM 與 DB2 WLM 的架構有點類似,也是通過服務類 (Service Class) 來分類管理的,同樣也是兩個層次:服務父類 (superclass) 和服務子類 (subclass)。服務類的資源管理和分配主要有以下兩種方式:
Class Resource Shares
在共享方式中我們需要定義每個服務類的資源占用比例。通過舉例子來解釋的話非常好理解,假設我們有 A、B、C 三個服務類,我們分別定義其 CPU 資源的為 50、30、20(注意,這裡並不是百分比,這裡可以使用的值范圍是 1 ~ 65536)。
那麼這時 A、B、C 可以使用的 CPU 比例為 50%、30%、20%。假如:
如果此時 C 處於非激活狀態的話,那麼 A 可以使用 CPU 比例為 (50/(50+30)) × 100% = 62.5%
如果我們添加一個新的服務類 D,share 值為 100,那麼 A 可以使用的 CPU 資源為 (50/(50+30+20+100)) × 100% = 25%
在這裡我們需要注意每個服務類的層次,因為服務父類和子類會影響到分配的范圍和比例。
Class Resource Limits
通過 limits 方式我們可以為服務類指定的限制有資源的最小和最大的百分比。具體的設置有:
min
分配給某個服務類的最小資源百分比。缺省值為 0。
softmax
在有沖突的情況下(這裡可以理解為資源緊張時),服務類可獲得的最少資源比例。在沒有沖突的情況下,服務類可獲得的資源可以超過該值設定的比例。缺省值 100。
hardmax
在沒有沖突的情況下,服務類可獲得的最大資源比例。缺省值為 100。
使用限制的時候需要注意以下規則:
最小值必須小於等於最大值
在同一層級同一個作用范圍內的所有服務類的最小值之和不能超過 100
同一服務類的 softmax 必須小於等於 hardmax
整合 DB2 WLM 與 AIX WLM
好了,上面我們稍稍對 AIX 的 WLM 做了下簡單的介紹。那麼,現在我們來看看以上兩者結合使用話又是如何工作的。
兩個 WLM 結合使用,關鍵就是要將 DB2 WLM 中的服務類與 AIX WLM 定義的服務類一個一個地關聯起來,這裡我們稱之為映射 (Mapping)。這樣在創建 DB2 WLM 的服務類的時候需要使用 OUTBOUND CORRELATOR 選項來指定關聯名稱。使用 DB2 WLM 將用戶或者程序名字定義成服務類,然後將 DB2 WLM 的服務類與 AIX WLM 的服務類通過 Outbound Correlator 相關聯,這就實現了對某個用戶或者應用程序限制 CPU 的功能了。
圖 -1 當中很清晰地看到,我們將 DB2 當中的父類對 AIX 的父類,DB2 中的子類對 AIX 當中的子類進行一對一的映射。
圖 1. 一對一的全映射
查看原圖(大圖)
在圖 -2 當中,是在一台主機上存在多個數據庫,而這裡我們僅僅對 DB2 和 AIX 的父類進行了映射。
圖 2. 對父類進行映射
查看原圖(大圖)
在圖 -3 中,也是多個數據庫的情況,這裡我們則是實現了子類的映射。
圖 3. 對子類進行映射
查看原圖(大圖)
其實 DB2 與 AIX 的服務類的映射可以是非常靈活的,並沒有太多限制。最關鍵的是,設計者必須非常清楚每個服務類所能夠分到的實際資源比例。因為我們是通過父類和子類來控制資源分配比例的作用范圍的,所以,從 AIX 的作用域映射到 DB2 以後,其實際的作用域我們必須非常清晰。
這裡有幾點我們是必須要知道的。首先,在 DB2 WLM 與 AIX WLM 兩者相結合的情況下,在 AIX WLM 當中我們只能夠對 CPU 資源進行管理。因為,說到內存方面,在 DB2 數據庫當中有專門屬於某個代理(agent)的私有內存(如 statement heap),同時也存在大量的各種共享內存區,比如緩沖池 (buffer pool),所以我們很難確定某個代理程序到底使用了多少內存。I/O 也一樣,一個代理程序要完成某條 SQL 指令,會導致許多其它的進程動作,比如預取進程 (prefetcher)、日志寫進程 (log writer) 等等。因此只能對 CPU 資源進行管理,不必遺憾,其實完全足夠了。
另外,DB2 WLM 不支持 AIX WLM 的繼承(inheritance)特性。因為一旦啟用了繼承特性,所有的子線程或者進程都會繼承成為其父線程或進程的屬性。這樣就導致了 DB2 WLM 當中的用標識定義的服務類失效。缺省情況下 AIX WLM 的繼承特性是啟用的,所以我們需要顯示地禁用。
最後還有一點要知道的是,一旦使用 AIX WLM 來管理 CPU 資源,那麼在 DB2 WLM 當中創建服務類的時候就不能設定其進程的優先級。既沒有這個必要,在語法上也不允許。
到目前為止,我們已經初步了解了 DB2 WLM、AIX WLM 以及兩者協作的原理。那麼接下來我們通過一個實際案例來帶大家看看我們是如何實現負載管理的目標的。
案例
這個例子雖然比較簡單,但具有一定的代表性,所以比較適合入門。
需求
客戶告訴我,他們有一個系統 A 需要開放一個只讀用戶給另一個系統 B 查數據,但他們希望這個只讀用戶的任何操作不能影響該系統的主營業務性能。這裡我們稍微整理一下需求:
在系統 A 數據庫開放一個用戶 testusr 給系統 B 使用;
限制用戶 testusr 只能讀取數據;
testusr 用戶的訪問不能占用過多性能影響主業務;
除 testusr 用戶以外以他用戶和程序不受限。
方案與分析
其實我們發現很多時候客戶的需求是有些籠統的,這就需要我們來具體化。上面的四條也還是不夠詳細,我們接下來結合具體技術來逐步分析。
一個只讀的 testusr 用戶,這很簡單,用權限去解決就好了。testusr 用戶的訪問不能影響主業務,這就比較籠統了,這需要我們更多地了解客戶的實際需求,並轉換為技術上很具體的東西。首先這裡很容易想到使用 AIX WLM 來限制 CPU 資源,這裡要注意 testusr 以外的用戶是不受限的,那麼我們為了簡化而選擇了 limits 方式沒有選擇 shares,原因是 shares 方式需要定義所有用戶的資源分配。
CPU 資源限制了,testusr 就一定不會影響主業務了麼?當然不是,還有很多方法可以占用較少 CPU 但是卻能夠極大程度地影響總體性能的方法 ( 或者說 SQL 語句 ),比如把磁盤帶寬占光。所以這裡我們通過了幾個方面來進一步限制。首先是限制並發連接數,不過 DB2 WLM 不能直接限制連接數,這點要通過 Query Patroller 這個組件來實現,這裡我覺得沒有必要把這個簡單場景的方案搞得這麼復雜,所以我們退而求次選擇了限制並發的活動協調代理數(CONCURRENTDBCOORDACTIVITIES)。這就是說我們允許有很大量的 testusr 用戶並發連接到數據庫,但是能夠同時運行 SQL 命令的只有有限的數量。作為補充,我們配合的加上一個限制會話的空閒等待時間(CONNECTIONIDLETIME),這樣就可以防止有過多的閒置會話浪費資源了。
對於資源占用有很重要的一點,我們知道,大多情況下很耗資源的 SQL 語句往往都是連接和排序導致的,而這兩個操作都是需要用到排序區和臨時表空間。那好,我們這裡再加上一項臨時空間的使用限制(SQLTEMPSPACE)。
將以上內容整理一下:
使用數據庫權限管理限制用戶只能查詢(這點不屬於 WLM 范圍所以在本文後續內容將略去);
使用 AIX WLM 的 limits 方式限制 testusr 用戶總體工作負載的總體 CPU 使用率;
使用 DB2 WLM CONCURRENTDBCOORDACTIVITIES 閥值控制 testusr 用戶並發 SQL 語句的執行數量;
使用 DB2 WLM CONNECTIONIDLETIME 限制 testusr 用戶會話活動之間允許的閒置時間。
使用 DB2 WLM SQLTEMPSPACE 限制 testusr 用戶能夠使用臨時表空間的容量。
客戶可能會問到:DB2 WLM 不是有一個閥值 ESTIMATEDSQLCOST 是限制開銷的麼,為什麼不用這個?這裡就要注意了,這個閥值的單位是 timerons,這個單位綜合考慮了 CPU、I/O 等各項資源的一個總體分值。在這裡的需求調查當中我們了解到,是允許 testusr 對一張大表做全表掃描的,我們知道如果只是單純地對一張巨型的表掃描其實對整體影響並不是很大(如果磁盤配置合理的話),但是 timerons 根據表的大小它的值是可大可小的。所以對於這個閥值我個人的建議是要根據應用類型來區分,OLTP 的應用可能更容易確定其范圍。
方案實施
1. 首先創建 DB2 WLM 的服務父類,這裡要使用 outbound correlator
db2 => create service class sc_test outbound correlator '_ScTest';
2. 創建 workload
db2 => create workload wl_test session_user ('TESTUSR') service class sc_test;
db2 => grant usage on workload wl_test to public;
3. 創建服務子類
db2 => create service class sc_test_querIEs under sc_test;
1. 首先創建 DB2 WLM 的服務父類,這裡要使用 outbound correlator
db2 => create service class sc_test outbound correlator '_ScTest';
2. 創建 workload
db2 => create workload wl_test session_user ('TESTUSR') service class sc_test;
db2 => grant usage on workload wl_test to public;
3. 創建服務子類
db2 => create service class sc_test_querIEs under sc_test;
4. 創建工作類集
db2 => create work class set wcs_querIEs
db2 (cont.) => (work class wc_read work type read);
5. 創建工作動作集
db2 => create work action set was_querIEs for service class sc_test
db2 (cont.) => using work class set wcs_querIEs
db2 (cont.) => (work action wa_read on work class wc_read
db2 (cont.) => map activity to sc_test_querIEs);
注意,由於我們這個例子比較的簡單,所以這裡定義的 work class set 和 work action set 也非常簡單,在一些復雜場景當中可能會是很復雜的,切不可生搬硬套。
6. 創建各項閥值
db2 => create threshold th_conn for service class sc_test
db2 (cont.) => ACTIVITIES ENFORCEMENT database
db2 (cont.) => when CONCURRENTDBCOORDACTIVITIES > 2 stop execution;
db2 => create threshold th_conn_idle for service class sc_test
db2 (cont.) => ACTIVITIES ENFORCEMENT database
db2 (cont.) => when CONNECTIONIDLETIME > 5 minutes stop execution;
db2 => create threshold th_querIEs_tmp for database
db2 (cont.) => ACTIVITIES ENFORCEMENT database partition
db2 (cont.) => when SQLTEMPSPACE > 10 M stop execution;
注意,我們這裡定義的閥值僅僅只是為了測試所以都比較小,不能供生產環境作為參考。另外提醒一點,定義閥值的時候,我們需要注意每一個閥值的定義域(definition domain)和執行范圍(enforcement scope)。由於篇幅原因,本文不再詳細列舉每個閥值的詳解。
7. 現在開始的步驟是配置 AIX WLM,需要以 root 權限操作。由於 AIX 的 WLM 需要一整套配置文件,為了簡便我們直接將其自帶的模板拿來用。
# cd /etc/wlm
# cp -r template inventory
# wlmcntrl – d inventory
這樣 aix 的 wlm 就啟動了,只是沒有任何配置。
8. 創建 AIX WLM 的服務類。
# mkclass -a inheritance=no -c hardmax='10' aixscquery
# lsclass -f -r
System:
memorymin = 1
Default:
Shared:
aixscquery:
inheritance = "no"
CPUhardmax = 10
這裡我們設定了 testusr 用戶僅僅能夠使用 CPU 的 10%,而且是硬限制。這裡我們
9. 配置 AIX WLM 的映射
# cd /etc/wlm/inventory
# vi rules
在文件尾加入
aixscquery - - - - - _ScTest
10. 將 WLM 重啟一下
# wlmcntrl -o
# wlmcntrl – a
11. 實施完成。
效果測試
CPU 資源
這裡是要檢驗 AIX WLM 能否作用在 DB2 的用戶連接上面,首先要檢查服務類的映射是否成功,讓 testusr 用戶連接上來隨便做一個查詢操作,然後查看 db2sysc 進程的線程信息:# ps -m -o THREAD,class -p 254084|awk '{print $1" "$2" "$3" "$4"
"$13" "$14}'
圖 4. 查看 db2sysc 進程的線程信息
這裡我們可以看到兩個 WLM 的服務類的映射已經成功。
接下來檢驗 CPU 資源限制是否成功,使用 testusr 用戶運行比較消耗 CPU 的命令,不管啟動多少個並發(當然在這裡由於我們的閥值限制了只能同時運行兩個並發),CPU 始終維持在 10% 一下。
圖 5. CPU 使用情況
查看原圖(大圖)
(查看大圖)
注意,這個測試過程當中沒有其它任何負載,我們可以看到 db2sysc 進程占用的 CPU 資源也基本不超過 10%。
好了,CPU 方面已經測試通過,接下來該看看 DB2 WLM 的閥值效果了。
並發活動工作
由於這裡不限制連接數,我們這裡首先用 testusr 用戶建立了三個會話,然後逐一運行一個比較長時間的 SQL 命令,到第三個運行時返回 SQL4712N 錯誤:
SQL4712N The threshold "TH_CONN" has been exceeded. Reason code = "6".
SQLSTATE=5U026
閒置時間
閒置時間的最小顆粒是 5 分鐘,如果設置的值不是 5 分鐘的整數倍的話會自動選擇一個最接近的 5 分鐘的整數倍。當閒置時間超過 5 分鐘,再次運行命令的話:
SQL1224N The database manager is not able to accept new requests, has
terminated all requests in progress, or has terminated your particular request
due to an error or a force interrupt. SQLSTATE=55032
排序空間
在運行一個少量數據的排序的話是沒有問題的,但是排序空間一旦超過 10MB 的話便會報錯(這裡將數據刪掉了)。
$ db2 "select * from db2inst1.testab order by dept,id
fetch first 10 rows only"
ID NAME DESC DEPT
--------- ----------- ----------- --------
...
...
...
...
10 record(s) selected.
$ db2 "select * from db2inst1.testab order by dept,id"
ID NAMEDESCDEPT
----- -------- ---------- ------
SQL4712N The threshold "TH_QUERIES_TMP" has been exceeded.
Reason code = "10". SQLSTATE=5U026
總體來看,將 DB2 WLM 和 AIX WLM 結合起來以後,基本上可以滿足在工作負載管理方面的絕大部分的需求。而且從效果上來說的話確實能夠達到我們的要求。