增強你的 sysbench - 給 TiDB 添加自定義測試

對于從事數(shù)據(jù)庫相關(guān)的同學(xué)來說,對數(shù)據(jù)庫進行性能測試是一個永遠繞不開的話題忽舟。這個世界上有很多的數(shù)據(jù)庫性能測試工具仰剿,而 sysbench 可以算是大家用的最多的之一全陨。

根據(jù)官網(wǎng)的介紹,sysbench 是一個基于 Luajit 的甚颂,多線程的腳本化的性能測試工具蜜猾,它不光能測試數(shù)據(jù)庫的性能秀菱,也可以測試文件 I/O,CPU 這些蹭睡,不過這里衍菱,我們重點來聊聊數(shù)據(jù)庫的測試。在 sysbench 里面肩豁,對于數(shù)據(jù)庫的測試脊串,用的最多的就是 OLTP 相關(guān)的腳本,譬如 oltp_point_select清钥,oltp_update_index琼锋。通常,OLTP 的腳本在絕大多數(shù)時候都夠用了祟昭,但程序員就是這么的不滿足缕坎,尤其是對我們這些開發(fā)數(shù)據(jù)庫的程序員來說,我們不光希望能測試 OLTP 相關(guān)的 workload篡悟,還希望能通過 sysbench 測試更多的 workload谜叹。

幸運的是,隨著 sysbench 1.0 的發(fā)布搬葬,它開始支持自定義的腳本來進行 benchmark荷腊,那么我們要做的事情就很簡單了,只需要干兩件事情:

  1. 學(xué)習(xí) Lua 這門腳本語言踩萎。
  2. 給 sysbench 寫自己的插件停局。

對于 Lua 語言,這里不做過多討論香府,即使你不會董栽,也不用特別擔(dān)心,它是一門非常容易學(xué)習(xí)的語言企孩。這里我們來談?wù)勅绾谓o sysbench 寫插件锭碳。

基本框架

這里,我們來實現(xiàn)一個 bank transfer 的 benchmark勿璃,首先我們創(chuàng)建一個 bank_transfer.lua 文件擒抛,在文件頭寫上

#!/usr/bin/env sysbench

然后基本的框架:

function thread_init() 
    print(string.format("start thread %d", sysbench.tid))
end

function thread_done()
    print(string.format("stop thread %d", sysbench.tid))
end

function event() 
end

在上面的文件里面,我們實現(xiàn)了三個函數(shù)补疑,thread_initthread_done 非常的直觀歧沪,就是 sysbench 在測試線程啟動和結(jié)束的時候調(diào)用,而 event 則是我們實際執(zhí)行測試的地方莲组,這里是空的诊胞。然后我們運行這個測試程序,你可以暫時忽略命令行里面的 MySQL 參數(shù)锹杈,這個后面我們會實際連接到 MySQL 進行測試撵孤。

sysbench --report-interval=1 --time=20 --threads=4 --mysql-host=127.0.0.1 --mysql-port=4000 --mysql-user=root --mysql-db=sbtest --db-driver=mysql bank_transfer run

start thread 0
start thread 2
start thread 1
start thread 3
Threads started!

stop thread 0
stop thread 3
stop thread 1
stop thread 2

傳遞參數(shù)

上面例子里面的參數(shù)其實是 sysbench 自己需要的參數(shù)迈着,對于我們的測試程序來說,它也可能需要一些參數(shù)邪码,所以我們在腳本里面定義自己的參數(shù)裕菠,如下我們定義了兩個參數(shù),table-sizetables闭专,用來告訴測試腳本奴潘,我們希望創(chuàng)建多少張表以及每張表里面有多少數(shù)據(jù)。

sysbench.cmdline.options = {
    table_size =
        {"Number of rows per table", 10000},
    tables =
        {"Number of tables", 1}
}

function thread_init() 
    print(sysbench.opt.table_size)
end

啟動的時候我們就可以指定自己的參數(shù)了喻圃,如下:

sysbench bank_transfer run --tables=16 --table-size=1000000

連接數(shù)據(jù)庫

因為我們是要對數(shù)據(jù)庫進行測試萤彩,所以首先我們需要跟數(shù)據(jù)庫建立起連接,在腳本里面寫上:

function thread_init() 
    drv = sysbench.sql.driver()
    con = drv:connect()
end

function thread_done()
    con:disconnect()
end

function event() 
    con:query("select 1")
end

上面我們在線程初始化的時候跟數(shù)據(jù)庫建立了連接斧拍,在結(jié)束的時候關(guān)閉了連接雀扶,而在 event 里面,則是執(zhí)行了 select 1 這個操作肆汹。重新執(zhí)行腳本愚墓,我們會看到如下輸出:

Threads started!

[ 1s ] thds: 4 tps: 24940.85 qps: 24940.85 (r/w/o: 24940.85/0.00/0.00) lat (ms,95%): 0.27 err/s: 0.00 reconn/s: 0.00
[ 2s ] thds: 4 tps: 28102.97 qps: 28102.97 (r/w/o: 28102.97/0.00/0.00) lat (ms,95%): 0.24 err/s: 0.00 reconn/s: 0.00

Prepare 和 cleanup

在開始測試之前,我們首先要導(dǎo)入數(shù)據(jù)昂勉,在 sysbench 里面浪册,這個是通過 prepare 來完成的,首先我們定義好 prepare 函數(shù):

function cmd_prepare()
    local drv = sysbench.sql.driver()
    local con = drv:connect()

    for i = sysbench.tid % sysbench.opt.threads + 1, sysbench.opt.tables, sysbench.opt
        .threads do 
        create_table(drv, con, i) 
    end
end

sysbench.cmdline.commands = {
    prepare = {cmd_prepare, sysbench.cmdline.PARALLEL_COMMAND}
}

上面我們定義了 cmd_prepare岗照,并且告訴 sysbench 這個是 PARALLEL_COMMAND 類型村象,也就是 sysbench 會并發(fā)的調(diào)用 prepare。而在 cmd_prepare 里面攒至,我們也是讓每個線程負責(zé)給不同的 table 導(dǎo)入數(shù)據(jù)厚者。

我們在 create_table 里面創(chuàng)建表結(jié)構(gòu),以及使用 bulk_insert_* 相關(guān)的接口來導(dǎo)入數(shù)據(jù):

function create_table(drv, con, table_num)
    print(string.format("Creating table 'account%d'...", table_num))

    local query = string.format([[
CREATE TABLE account%d(
  id INTEGER NOT NULL,
  balance INTEGER DEFAULT '1000' NOT NULL,
  PRIMARY KEY (id)
)]], table_num)

    con:query(query)

    if (sysbench.opt.table_size > 0) then
        print(string.format("Inserting %d records into 'account%d'",
                            sysbench.opt.table_size, table_num))
    end

    query = "INSERT INTO account" .. table_num .. "(id, balance) VALUES"

    con:bulk_insert_init(query)

    for i = 1, sysbench.opt.table_size do
        query = string.format("(%d, %d)", i, 1000)

        con:bulk_insert_next(query)
    end

    con:bulk_insert_done()
end

我們能 prepare迫吐,自然也會有對應(yīng)的 cleanup:

function cleanup()
    local drv = sysbench.sql.driver()
    local con = drv:connect()

    for i = 1, sysbench.opt.tables do
        print(string.format("Dropping table 'account%d'...", i))
        con:query("DROP TABLE IF EXISTS account" .. i)
    end
end

當定義好上面這些函數(shù)之后库菲,我們就可以使用 sysbench bank_transfer prepare 以及 sysbench bank_transfer cleanup 來導(dǎo)入或者清理數(shù)據(jù)了。

Transfer

好了志膀,現(xiàn)在到了最激動人心的時刻熙宇,我們開始寫真正的測試邏輯。我們這里要模擬的是 transfer溉浙,代碼如下:

function event() 
    local from = get_id()
    local to = get_id()
    local table_num = get_table_num()
    local amount = sysbench.rand.default(1, 100)
    while(from == to)
    do
        to = get_id()
    end

    con:query("BEGIN")

    local rs = con:query(string.format([[
SELECT id, balance FROM account%d WHERE id IN (%d, %d) FOR UPDATE
]], table_num, from, to))

    assert(rs.nrows == 2)

    local row_from = rs:fetch_row()
    local row_to = rs:fetch_row()

    if row_from[1] ~= from then
        row_from, row_to = row_to, row_from
    end 

    if row_from[2] - amount < 0 then 
        con:query("ROLLBACK")
        return 
    end

    con:query(string.format([[
UPDATE account%d SET balance = balance - %d WHERE id = %d
]], table_num, amount, from))

    con:query(string.format([[
UPDATE account%d SET balance = balance + %d WHERE id = %d
]], table_num, amount, to))

    con:query("COMMIT") 
end

可以看到烫止,邏輯還是非常簡單的,主要流程是:

  1. 開啟事務(wù)
  2. 隨機選擇兩個賬戶 from 和 to
  3. 查詢兩個賬戶的余額
  4. 如果 from 的余額不夠戳稽,轉(zhuǎn)賬失敗馆蠕,回滾事務(wù)
  5. 執(zhí)行轉(zhuǎn)賬操作,from 減去 amount,to 增加 amount
  6. 提交事務(wù)

運行測試荆几,可以看到如下輸出:

[ 1s ] thds: 4 tps: 661.92 qps: 3325.56 (r/w/o: 665.91/1331.82/1327.83) lat (ms,95%): 10.09 err/s: 0.00 reconn/s: 0.00
[ 2s ] thds: 4 tps: 678.85 qps: 3394.23 (r/w/o: 678.85/1357.69/1357.69) lat (ms,95%): 7.98 err/s: 0.00 reconn/s: 0.00
[ 3s ] thds: 4 tps: 894.98 qps: 4465.85 (r/w/o: 891.96/1783.93/1789.95) lat (ms,95%): 5.18 err/s: 0.00 reconn/s: 0.00

總結(jié)

上面通過一個簡單的例子,告訴大家如何在 sysbench 里面寫自己的測試赊时,我個人認為吨铸,作為一個非常通用的測試框架,會有越來越多的開發(fā)者給 sysbench 添加新的測試用例祖秒,譬如 Percona 已經(jīng)添加了 tpcc诞吱,blob,我自己后續(xù)也會嘗試在 sysbench 里面加入更多的測試 case竭缝,來對 TiDB 進行各種的性能測試房维。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市抬纸,隨后出現(xiàn)的幾起案子咙俩,更是在濱河造成了極大的恐慌,老刑警劉巖湿故,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阿趁,死亡現(xiàn)場離奇詭異,居然都是意外死亡坛猪,警方通過查閱死者的電腦和手機脖阵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來墅茉,“玉大人命黔,你說我怎么就攤上這事【徒铮” “怎么了悍募?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長战转。 經(jīng)常有香客問我搜立,道長,這世上最難降的妖魔是什么槐秧? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任啄踊,我火速辦了婚禮,結(jié)果婚禮上刁标,老公的妹妹穿的比我還像新娘颠通。我一直安慰自己,他們只是感情好膀懈,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布顿锰。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硼控。 梳的紋絲不亂的頭發(fā)上刘陶,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音牢撼,去河邊找鬼匙隔。 笑死,一個胖子當著我的面吹牛熏版,可吹牛的內(nèi)容都是我干的纷责。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼撼短,長吁一口氣:“原來是場噩夢啊……” “哼再膳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起曲横,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤喂柒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胜榔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胳喷,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年夭织,在試婚紗的時候發(fā)現(xiàn)自己被綠了吭露。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡尊惰,死狀恐怖讲竿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情弄屡,我是刑警寧澤题禀,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站膀捷,受9級特大地震影響迈嘹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜全庸,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一秀仲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧壶笼,春花似錦神僵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沛励。三九已至,卻和暖如春炮障,著一層夾襖步出監(jiān)牢的瞬間目派,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工胁赢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留址貌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓徘键,卻偏偏與公主長得像,于是被迫代替她去往敵國和親遍蟋。 傳聞我的和親對象是個殘疾皇子吹害,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • sysbench是一個模塊化的棒厘、跨平臺纵穿、多線程基準測試工具,主要用于評估測試各種不同系統(tǒng)參數(shù)下的數(shù)據(jù)庫負載情況奢人。它...
    一起代碼_尼科閱讀 11,209評論 0 53
  • 一谓媒、Sysbench介紹 SysBench是一個模塊化的、跨平臺何乎、多線程基準測試工具句惯,主要用于評估測試各種不同系統(tǒng)...
    張偉科閱讀 9,270評論 0 5
  • 前言 作為一名后臺開發(fā),對數(shù)據(jù)庫進行基準測試支救,以掌握數(shù)據(jù)庫的性能情況是非常必要的抢野。本文介紹了MySQL基準測試的基...
    hekang01閱讀 1,024評論 0 1
  • IP架構(gòu) sysbench部署服務(wù)器:172.17.100.107 壓測服務(wù)器:172.17.100.100 My...
    飛翔的Tallgeese閱讀 9,285評論 0 3
  • 開始之前先做個小實驗 今天登錄一臺測試機,發(fā)現(xiàn)MySQL服務(wù)起不來各墨,查看日志發(fā)現(xiàn)報錯 剛開始認為mysql庫中的幾...
    螞蟻爬上桂花樹閱讀 2,723評論 0 0