若能提升資料庫系統運作的效率,就可讓應用系統運作得更順暢。Google重新改寫malloc函式,並以gperftool為名釋出,而gperftool提供了tcmalloc動態函式庫。本文將利用tcmalloc來提升MySQL伺服器的執行效能,並採用tpcc-mysql針對MySQL進行效能的壓力測試。
資料庫系統在現行應用系統的運作中,一直都扮演舉足輕重的角色,往往資料庫系統的運作效能是應用系統運作是否順暢的關鍵,在一般的情況,良好的SQL程式或指令,通常就能夠解決大部分資料庫系統運作效率的問題。
除此之外,如果有辦法能提升資料庫系統程式運作的效率,倒也不失為一個提升資料庫運作效能的方法。
因此,本文將說明如何以gperftool(官方網址:https://github.com/gperftools/gperftools)提升MySQL資料庫(官方網址:https://www.mysql.com/)的運作效能。最後再說明如何利用MySQL資料庫壓力測試程式tpcc-mysql(官方網址:https://www.tpc.org/)量測MySQL資料庫的處理效能,藉此來比較優化後資料庫的運作效能。
什麼是Google Performance Tools
決定應用程式之執行效能的因素,除了系統的硬體效能外,另外一個重要因素是軟體撰寫的執行效率。在應用程式執行期間,除了需要強而有力的CPU運算能力進行相關計算外,往往同時也會需要一個儲存空間,用來儲存程式執行的過程所產生的資料,而後者通常會成為應用程式執行的效能瓶頸。
一般來說,若是須儲存的資料量不大,通常會利用存取速度快的系統記憶體(Memory)進行儲存以增快資料的存取速度,而不會儲存到慢速機械存取的系統磁碟(Disk),也因此很多的應用程式在執行的過程中,會依據需求動態地配置系統上的記憶體空間來儲存相關資料。
如果應用程式以C語言所撰寫,一般會利用malloc(Memory Allocation)函式來完成動態的配置記憶體工作。malloc是由glibc所提供用來動態配置指定大小之原始未初始化的記憶體空間,並在配置成功能回傳記憶體的開始位址,以供程式設計師使用。glibc是由GNU計畫所提供的C語言標準函式庫,可讓程式設計師方便取用其功能來加快程式開發的速度,其官方網址為「https://www.gnu.org/software/libc/」。
也因此,利用malloc函式配置系統記憶體的效率,往往也會影響程式執行的效率。為了提升malloc函式的執行效率,Google重新改寫malloc函式,並以「gperftool」為軟體名稱釋出。
gperftool除了提供tcmalloc動態函式庫(提供改寫後的malloc函式,以下稱為tcmalloc),也提供其他系統效能(如CPU效量)的測量工具程式。但由於本文主要在於說明如何利用tcmalloc來提升MySQL伺服器的執行效能,因此將採用tpcc-mysql來針對MySQL伺服器進行效能的壓力測試。
依據官方網站上的說明,tcmalloc主要著重在高效能的多線程(Multi-threaded)效率表現,意謂著可顯著地提升「高並發(High Concurrent)」的處理效率。所謂的「高並發」,指的是伺服器須在很短的時間內處理大量的要求。最常見的例子是春節的預售車票,往往在開放的當下,就會有大量的連線流量湧入,而此時伺服器便是在承受高並發的壓力,如果沒有優異的處理效能,往往會讓伺服器呈現癱瘓的情形而暫時停止服務。
安裝gperftools
在簡單介紹系統配置記憶體的機制後,接下來安裝gperftools。在安裝gperftools之前須先行安裝libunwind(在此安裝1.6.2版本)。首先至libunwind官方網站(https://download.savannah.gnu.org/releases)取得原始碼(在此使用1.6.2版本),以便進行編譯。
解壓縮原始碼後,編譯安裝libunwind軟體。先設定組態,如下組態為設定編譯成動態函式庫(Share Library)的形式並安裝於「/usr/local/libunwind」(安裝目錄)中:
./configure --enable-shared --prefix=/usr/local/libunwind
組態完成後,利用「make」指令進行編譯。在編譯成功後,再以「make install」指令將相關的程式及檔案安裝於「/usr/local/libunwind」目錄下,此時可檢查「/usr/local/libunwind/lib」是否有相關的動態程式庫(名稱為libunwind.so)等檔案。
安裝成功後,接著須設定「/etc/ld.so.conf」加上「/usr/local/libunwind/lib/」目錄名稱,並執行ldconfig指令來告知系統libunwind所在的目錄位置。安裝好libunwind後,就可繼續安裝gperftools(在此安裝的版本為2.9.1.)。
同樣地,至gperftools官方網站取得相關原始碼,在解壓縮後進行gperftools的組態設定,如下組態為啟用libunwind功能,並設定將相關的程式及檔案安裝於「/usr/local/gperftools」:
./configure --prefix=/usr/local/ gperftools --enable-libunwind
在組態完成後即進行編譯,執行「make」指令。在編譯成功後,同樣地以「make install」指令,將相關的程式及檔案安裝於「/usr/local/gperftools」目錄下。此時,可檢查「/usr/local/gperftools/lib」是否有相關的動態程式庫(名稱為libtcmalloc.so)等檔案。最後,同樣地在「/etc/ld.so.conf」檔案加上「/usr/local/gperftools/lib/」並執行「ldconfig」指令。
完成gperftools的安裝後,接著必須設定系統,讓MySQL伺服器在啟動時事先引用libtcmalloc來取代傳統glibc函式庫的malloc函式。在此,利用設定系統上的LD_PRELOAD環境變數的方式,讓MySQL在啟動時先行載入libtcmalloc動態函式庫。LD_PRELOAD主要是用來指定程式在執行之前要預先載入的動態函式庫位置,由於動態函式庫的特性,先行載入的函式並不會被後面載入的函式所覆蓋。
以本例而言,在MySQL預先戴入libtcmalloc動態函式庫所提供的malloc函式後,就不會再載入glibc動態函式庫中所定義malloc函式,因此達到置換malloc函式的目的。因此,可以利用MySQL伺服器所提供的mysqld_safe程式,這是一個由Bash語言所撰寫的MySQL伺服器管理程式,主要用來啟動MySQL伺服器及監控伺服器的服務情形。
可以在此檔案的第一行加上以下內容,來預先載入libtcmalloc,而後重新啟動MySQL伺服器:
export LD_PRELOAD=/usr/local/ gperftools/lib/libtcmalloc.so
在重新啟動後可利用lsof指令,執行「lsof -n | grep tcmalloc」指令來確認MySQL是否已載入libtcmalloc。如果輸出有libtcmalloc等字樣,就表示MySQL已成功使用libtcmalloc函式來取代傳統的malloc函式,如圖1所示。
接著,繼續安裝tpcc-mysql,並利用此工具來量測MySQL在使用libtcmalloc後的執行效能。
安裝tpcc-mysql
TPC(Tracsaction Processing Performance Council)是一個非營利型的資料庫評估組織,官方網址是「https://www.tpc.org/」,其主要的任務在於評估相關資料庫系統的功能及執行效能,而tpcc-mysql即為該組織開發用來評估MySQL資料庫效能的軟體。主要是利用壓測MySQL伺服器中的OLTP(Online Transactional Processing)服務的方式來測試MySQL的執行效能。
在簡單了解tpcc-mysql功能後,接下來開始安裝tpcc-mysql。
首先,執行如下的指令,以便取得相關原始碼:
git clone https://github.com/ Percona-Lab/tpcc-mysql.git
接著,到原始碼目錄中,執行make指令來編譯tpcc-mysql相關程式。要注意的是,系統上必須已安裝MySQL伺服器,並且mysql_config所在目錄路徑必須設定於系統的PATH環境變數中。
在編譯成功後,就會產生tpcc_load、tpcc_start兩個主要的程式,如下所述:
這是用來產生測試資料庫資料的程式,使用者可利用此程式來建立測試時所需要的測試資料,常用的命令組態如下所示:
-h:設定測試資料庫主機所在主機位置。
-P:設定資料庫伺服器所使用的通訊埠,通常為3306。
-d:設定儲存測試資料的資料庫名稱。
-u:設定連線資料庫主機所使用的使用者名稱。
-p:設定連線資料庫主機所使用的使用者密碼。
-w:設定要產生的資料倉儲數。這就是用來測試使用的數據數量,每個資料倉儲約可容納10萬筆紀錄,因此設定越多的資料倉儲數,就會花費越多的時間來產生測試資料。
實際執行資料庫效能測試的主程式,常用的命令組態如下所示:
-w:設定測試時使用的資料倉儲數(Warehouse),通常須與以tpcc_load所建立的資料倉儲數一致。
-c:設定測試時同時建立連線的連線數。
-r:設定儲存資料之所需的預備時間(warmup_time單位為秒),此時間通常用來將資料寫入系統記憶體中。
-l:設定要進行測試的時間(running_time,單位為秒),若未指定此參數,預設為20秒。
-i:設定產生測試報告的間隔時間(report_interval,單位為秒),若未指定此參數,預設為10秒。
-f:設定報表檔案的儲存位置,此檔案會儲存相關測試操作的輸出資料。
-t:類似報表檔案,但會輸儲存相關測試操作的輸出資料。
在簡單了解相關程式的用法後,接著產生測試需要的資料庫及相關資料。先新建一個名為「tpcctest」的資料庫,執行下列指令:
mysql -u [資料庫使用者名稱] –p [資料 庫使用者密碼] -e "create database tpcctest"
然後,利用tpcc-mysql所提供的create_table.sql(位於tpcc-mysql原始碼目錄中)來建立所需要的資料庫表格(Table),指令如下:
mysql -u [資料庫使用者名稱] -p [資料 庫使用者密碼] -D tpcctest
在建立相關的資料庫表格後,接著同樣利用add_fkey_idx.sql來設定資料庫表格相關表格欄位屬性(例如設定為索引(index)欄位),指令內容如下:
mysql -u [資料庫使用者名稱] -p [資料庫 使用者密碼] -D tpcctest
完成資料庫結構(Table schema)建置後,基本上會新建如下因應不同測試目的資料庫表格:
New-Order [新訂單],Payment [支付訂 單],Order-Status[訂單狀態] Delivery:[發貨狀態],Stock:[庫存] customer:[客戶],district:[地區]
tpcc_mysql便是利用上述的資料庫表格進行讀寫的效能測試,接著即可利用tpcc_load程式來產生相關的測試資料。
如下指令表示在本地端的資料庫主機上,產生100個資料倉儲的資料量(此階段可能會需要一點時間來產生):
tpcc_load -h localhost -d tpcctest -u root -p -w 100
在產生相關的測試資料後,以tpcc_start程式進行資料庫的效能測試,如下指令表示測試的資料倉儲的資料量為100(-w 100)並以同時10個連線(-c)、持續測試300秒(-l 300),以及每間隔20秒即須產生一份效能報告:
tpcc_start -h 127.0.0.1 -p 3306 -d tpcctest -u [資料庫使用者名稱] -p [資料 庫使用者密碼] -w 100 -c 10 -r 100 -l 300 -i 20 -f /var/log/tpcc_mysql.log
執行完畢,就會出現如圖2所示的效能報告(以逗號分隔的CSV格式),各列數據意義說明如下:
第一列:為間隔秒數資訊,在本例為每間隔20秒就會產生一次效能測試數據,故此欄位每隔20秒即會產生一筆完整的測試報告。
第二列:在間隔秒數(即20秒)中,針對新訂單資料庫表格(New-Order)新產生的訂單交易數量。此數值越高,代表效率越好。
第三列:針對新訂單資料庫表格測試交易中,所測試數量其中百分之95的平均回應(Response)時間,此數值越低,代表效率越好。
第四列:針對新訂單資料庫表格測試交易中,所測試數量其中百分之99的平均回應時間。
第五列:針對新訂單資料庫表格測試交易中,其中最長回應時間(max_rt)。
第六列:針對支付資料庫表格(Payment)的測試資訊,其格式為「支付資料庫表格測試數量|在測試過程的最長回應時間」。
第七列:針對訂單狀態資料庫表格(Order-Status)的測試資訊,其格式為「訂單狀態資料庫表格測試數量|在測試過程的最長回應時間」。
第八列:針對發貨狀態資料庫表格(Delivery)的測試資訊,其格式為「發貨狀態資料庫表格測試數量|在測試過程的最長回應時間」。
第九列:針對庫存資料庫表格(Stock)的測試資訊,其格式為「庫存資料庫表格測試數量|在測試過程的最長回應時間」。
tpcc-mysql安裝完成後,就可以用來測試MySQL使用tcmalloc前後的效能表現。
<本文作者:吳惠麟,多年資安經驗,喜好利用開源碼建構相關解決方案,著有「資訊安全原理與實驗」等書。>