sysbench花式採坑之一:自增值導致的TPS不可靠

沃趣科技發表於2018-10-15

那是一個風和日麗的春天,本人在讀了幾篇sysbench的使用文件,外加找朋友要了個sysbench安裝包,裝上跑了一下後,感覺sysbench也就這麼回事,自己已經完全掌握了,可以遊刃有餘的應對公司交給我的測試專案了。沒錯,科學證明,真的不要亂立flag,這樣會很扎心的。總之,懷著自信滿滿的心情,我遇到了測試過程中的第一個問題。


| MySQL非同步複製效能低於MGR架構

這次測試需要測一下架構之間的效能對比,一開始走勢是非常好的,非同步複製效能高於半同步複製,嗯,很符合預期嘛,前景一片良好,那測一下MGR吧,我十分瀟灑的搭架構,造資料,手起刀落,臥槽,什麼鬼,MGR的效能竟然比非同步複製的效能還要高?!

“感受停在我發端的指尖,如何瞬間凍結時間”,當時我的心情就像現在聽的這首《光年之外》,啦啦啦啦,我沒想到~。懷著慈悲為懷的心情,我回去對比了一下MGR和非同步複製的配置檔案,發現兩者之間除了MGR的專用配置外,其他配置均相同,那麼問題大概是出在MGR的專用配置上了,當時我忘記戴上的眼鏡片上精光一閃,呵呵,又被我看穿了。

針對MGR的專用配置,本人又去回過頭翻了一下文件,好吧,沒找到什麼,MGR就這麼些配置項,不論哪個都看起來都和我效能測試沒關係呀。

transaction_write_set_extraction = XXHASH64
#plugin-load='group_replication=group_replication.so'
## [group replication variables]
group_replication_group_name = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
group_replication_start_on_boot = off
group_replication_bootstrap_group = off
group_replication_local_address = '172.17.0.1:33061'
group_replication_group_seeds ='172.17.0.1:33061,172.17.0.2:33061,172.17.0.3:33061'
#group_replication_single_primary_mode = off
group_replication_single_primary_mode = on
#group_replication_enforce_update_everywhere_checks = on
group_replication_enforce_update_everywhere_checks = off
group_replication_ip_whitelist='127.0.0.1/32,172.17.0.0/16'

那會不會是造的資料量不一樣?於是我select count統計了一下,發現確實都是500W行呀,保險起見,看一下最大ID吧,因此我執行了一下select max(id) from sbtest1;非同步複製上得到了500W的結果,MGR上得到了3500W的結果,嗯,兩個相等,看來不是這裡…….呸,等下,哪裡相等了?!

WTF,同樣的造數語句竟然造出不一樣的資料,此時歌曲切換到了小生的花傘還落在你家,好吧,歌詞並沒有表達出我當時的心意。於是我select * from sbtest1 limit 10看了一下,愣是用我的24K硬化氪金泰坦精鋼,呵呵,我是不會說狗眼的,於細微處看出了不同,發現非同步複製中ID列的結果是[1,2,3,4,5,6,7,8,9,10],在看MGR中,ID列的結果是[3,10,17,24,31,38,45,52,59,66],唉,這麼不明顯的差別也就只有我能看出來了。

既然找到了明顯的不同,那會不會是這個問題造成了MGR效能高於非同步複製的現象呢?於是我在周身用我僅剩的幾塊靈石擺了一個聚靈陣,在陣法內打坐冥想,神識先是在體內執行了12個小周天,過手太陰肺經,經列缺、天府、中府幾大要穴,然後自頭頂衝竅而出,於青蓮幻境之中開始了推演,終於發現這就是我要的滑板鞋…

從ID列的結果可以看出,兩種架構的自增值是不一樣的,那自增值不同為什麼會出現效能不同的現象呢,先耗費些許靈力把我冥想中的圖煉化兩幅出來吧。

(左為非同步複製資料樣圖,右為MGR資料樣圖)


根據sysbench的原始碼來看,sysbench在做oltp的時候,select、update都是根據輸入的行數大小隨機生成一個ID來進行。

...
rs = db_query("SELECT c FROM ".. table_name .." WHERE id=" .. sb_rand(1, oltp_table_size))
...
query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size)
...

而delete和insert是對同一個隨機生成的ID進行操作的。

i = sb_rand(1, oltp_table_size)
rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. i)
...
rs = db_query("INSERT INTO " .. table_name .. " (id, k, c, pad) VALUES " .. string.format("(%d, %d, '%s', '%s')",i, sb_rand(1, oltp_table_size) , c_val, pad_val))

既然ID是隨機生成的,那麼問題就來了,在MGR架構中,如果生成一條ID為3或者10的SQL語句,這些語句是可以正常執行的,但如果生成了ID為4或5或6的SQL語句,在MGR架構中這些ID是不存在的,因此這就是一條空DML,這種空DML速度是非常快的,而且還會計入sysbench的tps的結果,這樣自然會造成MGR架構的效能測試結果偏高。

既然找到了MGR效能偏高的原因,那造成MGR和非同步複製中ID不一致的原因又是什麼呢?在經驗上來說,這種情況99.9%就是自增造成的,於是我又看了一下MGR的配置描述,果然注意到了之前一眼掃過去就排除嫌疑的MGR專門控制自增的引數。

group_replication_auto_increment_increment

把這個引數設定為1,重新進行造數,發現MGR中的資料和非同步複製中的ID保持了一致,效能測試結果也恢復了正常。

總之,這是自增值對sysbench壓測帶來的一個坑,那自增值會不會還有其他坑呢?嗯,今日氣衝斗府,微盈相沖,正是閉關的好時機,我必須去閉個關了,先升它一個小境界。


| 作者簡介

李文航·沃趣科技資料庫技術專家

熟悉MySQL體系結構和工作原理、SQL調優、資料庫故障診斷、資料遷移、備份恢復

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28218939/viewspace-2216341/,如需轉載,請註明出處,否則將追究法律責任。

相關文章