LinkedIn有超過500個內部應用程序基于MySQL。為了便于管理,提高利用率,他們構建了MySQL即服務模型。該模型有個缺點,一個應用程序的查詢可能會影響其他應用程序的查詢。為了控制查詢,他們希望收集數據庫中運行的查詢的完整信息,以便分析優化。近日,LinkedIn工程師Karthik Appigatla撰文介紹了他們在這方面所做的工作。
MySQL Performance Schema是擺在他們面前的一個選項。MySQL從5.5.3版本開始提供這個特性,它可以從底層監控MySQL服務器的運行。這種方法的缺點是,啟用或禁用performance_schema需要重啟。而且,啟用該模式會增加大約8%到25%的開銷。另外,分析Performance Schema的結果也異常復雜。
還有一個選項是借助查詢日志。他們可以預先設定一個閾值,并把所有超過閾值的查詢記錄在一個文件里用于后續分析。這種方法的缺點是無法捕獲所有查詢。雖然將閾值設為0可以捕獲所有查詢,但那會導致非常高的I/O,嚴重降低系統吞吐量,所以,他們一開始就沒有考慮使用這種方式。
為了保證開銷最小同時又能有效地度量所有查詢,他們構建了Query Analyzer。該工具包含三個組件,如下圖所示:
代理——運行在數據庫服務器上。中央服務器——存儲查詢信息;UI——位于中央服務器之上,用于展示SQL分析結果。Query Analyzer的高層架構
其中,代理使用原始套接字捕獲TCP數據包并解碼,然后使用MySQL Protocol從數據包流構建出查詢。它會計算查詢的響應時間,并將查詢發送給一個Go例程(他們使用了Percona GO程序包),由后者識別出查詢指紋。代理會以這個指紋為基礎計算生成一個哈希值,作為查詢的KEY。代理會把查詢的哈希值、總響應時間、次數、用戶、數據庫名稱等信息存儲在哈希表中。如果服務器執行了哈希值相同的查詢,那么次數及總響應時間會增加。此外,代理還會存儲查詢的元數據,包括查詢的哈希值、指紋、第一次執行時間、最大時間、最小時間等。代理會定期將收集到的信息發送給中央服務器,并重置計數器。元數據信息只有在發生變化時才會發送。該代理只需要幾個MB的內存來管理這些數據結構,而其發送信息所占用的帶寬則可以忽略不計。
UI會顯示所有不同的查詢,如下圖所示:
其中有個有趣的指標是查詢負載占比,查詢負載的計算方法為:
而查詢負載占比的計算方法為:
查詢負載占比高的查詢是需要特別關注的,即使該查詢的單次執行時間并不長。點擊任意查詢,可以查看該查詢的趨勢圖及其他更多信息,如下圖所示:
LinkedIn使用sysbench在MySQL 5.6.29-76.2-log Percona Server (GPL)上做了基準測試。當并發線程小于128時,Query Analyzer基本不會影響吞吐量。當并發線程數到達256時,每秒事務數減少了5%,這仍然好于Performance Schema的10%。在整個測試過程中,Query Analyzer占用的CPU不足1%,當并發線程數超過128時,其占用的CPU也僅為5%。
Query Analyzer可以帶來許多好處。數據庫工程師可以快速定位有問題的查詢,高效地分析解決數據庫速度變慢的問題。開發人員和業務分析師可以查看查詢趨勢,檢查查詢負載。在安全方面,Query Analyzer可以在數據庫收到新的查詢請求時發出警告。
最后,雖然時間還沒有確定,但LinkedIn的最終目標是將Query Analyzer開源。