Mysql

從日誌文件重放(重新執行)MySQL SELECT 查詢

  • October 22, 2021

MySQL 基準測試

我想通過重新執行來自日誌文件的真實查詢來評估不同 MySQL 實例的性能。我知道像 mysqlslap 這樣的工具會產生隨機和自動生成的查詢,但我更願意用實際的查詢來測試系統。

為了對新系統進行基準測試,理想情況下,我會使用慢日誌或通用日誌收集所有查詢,然後將查詢重播到新系統。

應該可以過濾查詢,例如我只想重播 SELECT 語句。我想知道是否存在積極維護的程序或最佳實踐來實現預熱或基準測試功能。

要求

  • 重放(重新執行)從正在執行的 MySQL 實例收集的真實查詢
  • 按語句類型(INSERT、UPDATE、DELETE)和 DML 過濾語句
  • 獲取統計資訊(查詢在遷移之前、遷移之後執行了多長時間等)

問題:工具已過時

Percona 提供了幾個似乎是為此目的而設計的工具。所有這些都已從目前的 Percona Toolkit 中刪除。這些工具是:

  • pt日誌播放器
  • pt-query-digest 的重播選項
  • 查詢回放

潛在的解決方案

使用 Debian Wheezy docker 容器可以輕鬆訪問 pt-log-player 可用的舊 Percona Toolkit 版本。執行一個容器docker run -it --network="host" --name wheezy debian:wheezy /bin/bash並在其中安裝舊版本:

apt-get update
apt-get install percona-toolkit mysql-client

我也嘗試過 percona-playback,但它似乎也沒有得到非常積極的維護。那將是一個很棒的工具,但它幾乎沒有文件記錄,而且我找不到僅過濾 SELECT 語句的方法,因為我不想執行其他 DML 語句。我只看到 Percona Server 提供了一個啟用只讀選項的標誌,但這不適用於 vanilla MySQL 或 AWS RDS。

但是,我寧願使用不依賴於未維護工具的過程。

想像的工作流程

  1. 啟用慢查詢日誌或通用日誌
  2. 解析和分析日誌文件
  3. 過濾相關查詢
  4. 重新執行查詢
  5. 比較結果

有什麼工具可以實現這一目標嗎?過濾慢查詢日誌的最佳方法是什麼?如何合理地重播查詢?

我找到了解決我的問題的方法。它是 Percona pt-query-digest 和 Percona 播放的組合。

首先,我通過數據庫名稱過濾慢日誌,並排除所有不以.開頭的語句select

cat mysql-slow.log |  pt-query-digest --filter '(($event->{db}) =~ /my_database/) && $event->{arg} =~ m/^select/i' --output slowlog > my_database_selects.log

作為輸出,我得到一個新的慢日誌文件,其中只包含所需的查詢。

percona-playback --mysql-max-retries 1 --mysql-host example.org --mysql-port 3306 --mysql-username warmup --mysql-password S-E-C-R-E-T --ignore-row-result-diffs --query-log-file ~/my_database_selects.log

結果,我大致了解了查詢執行時間和預熱的數據庫。

Detailed Report
----------------
SELECTs  : 41666 queries (33379 faster, 8287 slower)
INSERTs  : 0 queries (0 faster, 0 slower)
UPDATEs  : 0 queries (0 faster, 0 slower)
DELETEs  : 0 queries (0 faster, 0 slower)
REPLACEs : 0 queries (0 faster, 0 slower)
DROPs    : 0 queries (0 faster, 0 slower)


Report
------
Executed 41666 queries
Spent 00:00:45.795945 executing queries versus an expected 00:02:07.966942 time.
33379 queries were quicker than expected, 8287 were slower
A total of 0 queries had errors.
Expected 79870 rows, got 79868 (a difference of 2)
Number of queries where number of rows differed: 0.

Average of 265.39 queries per connection (157 connections).

我希望這可以幫助有類似問題的人。

安裝 Percona 播放

目前版本中存在需要更改庫路徑的錯誤。

sudo apt-get install libtbb-dev libmysqlclient-dev libboost-program-options-dev libboost-thread-dev libboost-regex-dev libboost-system-dev libboost-chrono-dev pkg-config cmake  libssl-dev
git clone https://github.com/Percona-Lab/query-playback.git
cd query-playback/

編輯文件CMakeLists.txt (在目錄 ~/git/query-playback/percona_playback/mysql_client/CMakeLists.txt中)並將 find_library(MYSQL_LIB"mysqlclient_r" PATH_SUFFIXES “mysql”)替換為find_library(MYSQL_LIB “mysqlclient” PATH_SUFFIXES “mysql “)(刪除 _r 後綴)。

mkdir build_dir
cd build_dir
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
make
sudo make install

這是一個有一些背景的連結

由於pt-query-digest在為 MySQL 5.6 和 MariaDB 10.3 生成的一般日誌上對我不起作用,我環顧四周,發現mysql-utilities正在執行簡單的解析,但期望每個查詢的日期/時間。所以最後我只是重做了非常簡單的解析:

rm -rf /tmp/sql-reqs ; mkdir /tmp/sql-reqs ; perl -lne 'if (/^(\d{6} (\d{1,2}:\d{2}:\d{2})|\t)\t *(\d+) (\w+)\t(.*)/) { open $F, ">>", "/tmp/sql-reqs/$thread.sql"; print $F "$arg;" if $type eq "Query" && $arg =~ /^(select|set)/i; $thread = $3; $type = $4; $arg = $5 } else { $arg .= " $_" } ' /var/lib/mysql/xxx.log

然後你可以重播做一個簡單的:

time sh -c 'for i in /tmp/sql-reqs/*.sql; do cat $i | mysql _MY_DB_ >/dev/null & done; wait'

注意:在從不使用準備好的語句的應用程序(moodle)上進行測試。

引用自:https://dba.stackexchange.com/questions/218736