作者:盧文雙 資深資料庫核心研發
去年年底通過微信公眾號【資料庫核心】設定了一個目標——2023 年要寫一系列 特性介紹+核心解析 的文章(現階段還是以 MySQL 為主)。
雖然關注者很少,但本著「說到就要做到」的原則,從這篇就開始了。
序言:
以前對 MySQL 測試框架 MTR 的使用,主要集中於 SQL 正確性驗證。近期由於工作需要,深入瞭解了 MTR 的方方面面,發現 MTR 的能力不僅限於此,還支援單元測試、壓力測試、程式碼覆蓋率測試、記憶體錯誤檢測、執行緒競爭與死鎖等功能,因此,本著分享的精神,將其總結成一個系列。
主要內容如下:
由於個人水平有限,所述難免有錯誤之處,望雅正。
本文是第一篇入門篇。
本文首發於 2023-03-18 21:58:52
本系列基於 MySQL 8.0.29 版本,且主要在 Ubuntu 22.04 X86_64 驗證(部分指令也在 Ubuntu 20.04 X86_64、Ubuntu 22.04 ARM64、MacOS M1 做了驗證),如有例外,會特別說明。
在修改核心程式碼後,不僅需要測試新增功能,同時也要對原有功能做迴歸測試,以保證新加程式碼對原有功能沒有影響,這就需要用到 MySQL 原始碼自帶的測試框架 mtr。
MySQL 測試框架是一個以 MySQL 框架和內部引擎為測試物件的工具,主要執行指令碼在安裝路徑(make install
後的路徑)下的mysql-test
目錄,基本覆蓋了所有 MySQL 的特性和異常情況。
MySQL 測試框架 mtr 主要包含如下幾個元件:
--source
,--replace_column
等)都在command_names
和enum_commands
兩個列舉結構體中。--valgrind
或 --valgrind-mysqltest
選項,才會用到 mysql_client_test
。除此之外,還提供了單元測試工具(嚴格來說不屬於 mtr ),以便為儲存引擎和外掛建立單獨的單元測試程式。
由於 MySQL 測試框架的入口是 mysql-test-run.pl(它會呼叫上述其他元件),因此,一般將 MySQL 測試框架簡稱為 mtr。
mtr 採用t/r
模式(t
目錄中儲存具體的測試 case,檔案以.test
結尾;r
目錄中儲存了對應 case 的期望結果,檔案以.result
結尾),主要測試步驟是「通過執行一個 case,將該 case 的輸出結果,與標準的輸出結果(期望結果)作 diff」:
如果t
目錄中的某個 case 在r
目錄中沒有對應.result
檔案:
上文說的 case 是指一系列的語句,包括 SQL 語句和一些必要的 mysqltest command。
所有 case 可分為三部分,分別為:
mysql-test/t
目錄,期望結果(如果有的話)位於mysql-test/r
目錄,二者中的檔案是一一對應的,比如:mysql-test/t/alter_debug.test
、mysql-test/r/alter_debug.result
。mysql-test/suite
目錄,其中包含很多測試 case 的集合,每個集合都是一個單獨的子目錄(比如 mysql-test/suite/binlog
),在子目錄中又分別包含 r、t 兩個目錄。mysql-test/extra/
目錄,在 8.0.29 版本中只包含binlog_tests
、rpl_tests
兩個集合。mysql-test-run.pl
框架執行流程如下:
1、初始化(Initialization)。
disabled.def
檔案、--skip-xxx
命令(比如skip-rpl
)等確定執行用例。2、執行用例(run test)。
主執行緒根據引數--parallel
(預設是 1)啟動一個或者多個用例執行執行緒(worker),各執行緒有自己獨立的 client port,data dir 等。
啟動的 worker 與主執行緒之間是 server-client 模式,主執行緒是 server,worker 是 client。
以 rpl.rpl_multi_source_basic
測試 case 為例來說明執行過程。
# This is the basic test required in for multisource replication
# The aim of this file is to test the basic usecases of msr.
# 0. Create two masters and a slave and setup a multisource replication
# between them.
# 1. create a different databases on each master and test if they are replicated
# to the slave.
# 2. create a different table on each master and test if they are replicated to
# the to the slave.
# 3. Create a table with the same name on both masters and update non conflicting
# data on that table. Test if the replication is done properly.
# 4. Check if updates happen on different master such that the resulting
# data on slave is conflicting, check that one of the channels the slave
# SQL thread is stopped.
#
#
# Note: Out of convention, server 2 is always made a slave for multisource testing.
啟動測試指令 perl mysql-test-run.pl --do-test=rpl_multi_source
後,會啟動 3 個 mysqld 程序,其中 2 個 master 節點,1 個 slave 節點:
➜ rpl ps -xf | grep mysql
6982 pts/2 S+ 0:00 \_ perl mysql-test-run.pl rpl_multi_source_basic
7125 pts/2 S+ 0:00 \_ perl mysql-test-run.pl rpl_multi_source_basic
7130 pts/2 S+ 0:00 \_ /data/work/mysql/mysql80-install.bak_valgrind/bin//mysqltest_safe_process -- /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.1 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file
7131 pts/2 Sl 0:04 | \_ /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.1 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file
7132 pts/2 S+ 0:00 \_ /data/work/mysql/mysql80-install.bak_valgrind/bin//mysqltest_safe_process -- /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.2 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file
7133 pts/2 Sl 0:06 | \_ /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.2 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file
7134 pts/2 S+ 0:00 \_ /data/work/mysql/mysql80-install.bak_valgrind/bin//mysqltest_safe_process -- /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.3 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file
7135 pts/2 Sl 0:04 | \_ /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.3 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file
7283 pts/2 S+ 0:00 \_ /data/work/mysql/mysql80-install.bak_valgrind/bin//mysqltest_safe_process -- /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqltest --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --silent --tmpdir=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/tmp --character-sets-dir=/data/work/mysql/mysql80-install.bak_valgrind/share/charsets --logdir=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/log --database=test --plugin_dir=/data/work/mysql/mysql80-install.bak_valgrind/lib/plugin --timer-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/log/timer --test-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/suite/rpl/t/rpl_multi_source_basic.test --tail-lines=20 --result-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/suite/rpl/r/rpl_multi_source_basic.result
7284 pts/2 R 0:00 \_ /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqltest --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --silent --tmpdir=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/tmp --character-sets-dir=/data/work/mysql/mysql80-install.bak_valgrind/share/charsets --logdir=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/log --database=test --plugin_dir=/data/work/mysql/mysql80-install.bak_valgrind/lib/plugin --timer-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/log/timer --test-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/suite/rpl/t/rpl_multi_source_basic.test --tail-lines=20 --result-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/suite/rpl/r/rpl_multi_source_basic.result
可見:
--defaults-group-suffix=.1 到 3
分別對應 3 個 mysqld 程序,說明 mtr 不是靠 mock 的形式來測試的,而是啟動真 mysqld 程序來測試。mysql-server 編譯需要:
# for mysql 8.0
sudo apt install gdb gcc g++ cmake -y
sudo apt install openssl libssl-dev -y
sudo apt install libncurses-dev libudev-dev -y
sudo apt install bison flex libaio-dev libreadline-dev libjemalloc-dev -y
sudo apt install libevent-dev zlib1g-dev libmecab-dev libgcrypt20-dev -y
sudo apt install libsasl2-dev libldap2-dev libtirpc-dev
sudo apt-get install libsasl2-dev # SASL
sudo apt-get install slapd ldap-utils # LDAP
sudo apt install valgrind doxygen libcurl4-gnutls-dev -y # extra
# centos 7.6
sudo yum install cmake gcc g++ # 由於 cmake、gcc 版本偏低,需要自行通過原始碼編譯安裝
sudo yum install readline-devel bison flex libarchive openssl-devel
sudo yum install rpcgen libudev-devel ncurses-devel libtirpc libtirpc-devel
sudo yum install cyrus-sasl-devel # SASL
sudo yum install openldap openldap-devel # LDAP
sudo yum install valgrind # extra
# centos stream 9
sudo yum install cmake gcc g++ gcc-toolset-12-gcc gcc-toolset-12-gcc-c++ gcc-toolset-12-binutils
sudo yum install readline-devel bison flex libarchive openssl-devel # libtirpc-devel
sudo yum install rpcgen libudev-devel ncurses-devel libtirpc libtirpc-devel
sudo yum install cyrus-sasl-devel # SASL
sudo yum install openldap openldap-devel # LDAP
sudo yum install valgrind # extra
# macos
brew install lz4
brew install zlib
brew install clang
由於系統及版本差異,這裡羅列的軟體包可能會有所缺失,版本也可能會有所不同。
對於 mtr 來說,也需要額外安裝一些依賴:
# centos
yum -y install perl -y
sudo yum install perl-JSON -y
sudo yum install perl-Test-use-ok.noarch -y
# ubuntu
sudo apt install perl -y
sudo perl -MCPAN -e 'install JSON'
Debug 版本編譯選項範例:
# for MacOS and Ubuntu
CURDIR=`pwd`
INSTALLDIR=$CURDIR/../../mysql80-install
DATADIR=$CURDIR/../../mysql80-default-data
BOOSTDIR=$CURDIR/../../boost_1_77_0
rm CMakeCache.txt -f
cmake .. \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_INSTALL_PREFIX=$INSTALLDIR \
-DSYSCONFDIR=/etc \
-DMYSQL_DATADIR=$DATADIR \
-DMYSQL_UNIX_ADDR=/tmp/mysqld.sock \
-DMYSQL_TCP_PORT=3306 \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_DEBUG=1 \ # 必須是 debug 版本
-DWITH_BOOST=$BOOSTDIR \
-DWITH_SSL=/usr/local/openssl-1.1.1 \
-DFORCE_INSOURCE_BUILD=1
# -DWITH_ASAN=ON -DWITH_ASAN_SCOPE=ON -DWITH_UBSAN=ON \ # 選擇啟用哪些元件
# -DWITH_VALGRIND=ON \
# -DENABLE_GCOV=1 -DENABLE_GPROF=1 \
if [ $? != 0 ]; then
exit 1
fi
# for MacOS, only need make
make -j4
make install
Release 版本編譯選項範例:
#!/bin/bash
# for MacOS and Ubuntu
CURDIR=`pwd`
# for 8.0.29
INSTALLDIR=$CURDIR/../../mysql80-install
#INSTALLDIR=/usr
DATADIR=$CURDIR/../../mysql80-default-data
BOOSTDIR=$CURDIR/../../boost_1_77_0
rm CMakeCache.txt -f
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_CONFIG=mysql_release \
-DFEATURE_SET=community \
-DWITH_EMBEDDED_SERVER=OFF \
-DWITHOUT_ROCKSDB=ON \
-DWITH_UNIT_TESTS=OFF \
-DWITH_BOOST=$BOOSTDIR \
-DFORCE_INSOURCE_BUILD=1 \
-DCOMPILATION_COMMENT="MySQL build $(date +%Y%m%d.%H%M%S.$(git rev-parse --short HEAD))"
#-DCMAKE_INSTALL_PREFIX=$INSTALLDIR \
#-DSYSCONFDIR=/etc \
#-DMYSQL_DATADIR=$DATADIR \
#-DWITH_MYISAM_STORAGE_ENGINE=1 \
#-DWITH_INNOBASE_STORAGE_ENGINE=1 \
#-DWITH_MEMORY_STORAGE_ENGINE=1 \
#-DWITH_PARTITION_STORAGE_ENGINE=1 \
if [ $? != 0 ]; then
exit 1
fi
# for MacOS, only need make
make -j4
make install
-DCMAKE_BUILD_TYPE=type
選項說明:
The type of build to produce:
RelWithDebInfo
: default value。Enable optimizations and generate debugging information. This is the default MySQL build type.Release
: Enable optimizations but omit debugging information to reduce the build size. This build type was added in MySQL 8.0.13 (MySQL 5.7 is not supported).Debug
: Disable optimizations and generate debugging information. This build type is also used if the WITH_DEBUG
option is enabled. That is, -DWITH_DEBUG=1
has the same effect as -DCMAKE_BUILD_TYPE=Debug
.編譯安裝後,mysql-test
目錄樹結構如下:
mysql-test
├── README
├── README.gcov # 程式碼覆蓋率測試說明,最後更新於2006年
├── README.stress # 壓力測試說明,針對 mysql-stress-test.pl ,最後更新於2006年
├── collections # 該目錄下的檔案是官方推薦的迴歸測試指令集
│ ├── README # 說明檔案
│ ├── coverage.ignore # 指定需要忽略程式碼覆蓋率測試的目錄
│ ├── disabled.def # 列出需要臨時禁用的測試用例,在執行測試時會跳過
│ ├── disabled-asan.list # 除 disabled.def 檔案所列用例之外,還需要臨時禁用的測試用例
│ ├── disabled-ubsan.list # 同上
│ ├── disabled-valgrind.list # 同上
│ ├── disabled_ndb.def # 僅在執行 MySQL Cluster 時才需要臨時禁用的測試用例
# 適合每天都執行的迴歸測試指令集
# 涵蓋 default suites、非 default suites、針對複製和binlog的擴充套件測試(區分不同的複製引數)、InnoDB 擴充套件測試(區分不同頁面大小)
│ ├── default.daily
# 由於 valgrind 執行比較耗時,因此,該指令集只能涵蓋除 big-test 之外的所有 suites 。
# 需要編譯時新增選項 -DWITH_DEBUG=1 -DWITH_VALGRIND=1 的情況下,才能執行 valgrind 測試。
# 注意:通過實測、分析程式碼,執行 mtr 時必須新增 --valgrind 選項才能用到 valgrind 元件。
│ ├── default.daily-valgrind
# 適合每週執行一次的指令集,執行耗時能達到48小時。
# 是 default.daily 的超集,同時,還指定了 --debug-server 。
# 覆蓋 default suites + 非 default suites + 複製和binlog的擴充套件 + InnoDB擴充套件 + 其他按周執行的指令集。
│ ├── default.weekly
│ ├── default.weekly-ndbcluster # 覆蓋 default.daily + ndbcluster + 部分非預設指令集
│ ├── default.weekly-protocol # 編譯時需要設定 DWITH_TEST_TRACE_PLUGIN=1,只覆蓋 main suite。
# 在啟用 --big-test 和 --debug-server 選項的前提下,執行所有的指令集。
# 需要編譯時新增選項 -DWITH_DEBUG=1 -DWITH_VALGRIND=1 的情況下,才能執行 valgrind 測試。
# 注意:通過實測、分析程式碼,執行 mtr 時必須新增 --valgrind 選項才能用到 valgrind 元件。
│ ├── default.weekly-valgrind
│ ├── default.weekly.basic # 在禁用 --big-test 選項的前提下,執行所有的指令集,即包含 default suites + 非 default suites。
# 適用於每次push程式碼時執行的指令集,能控制在一個小時內。
# 更適用於 mysql 5.7 版本。
│ ├── default.push
│ ├── default.push-ndbcluster # 分為 default suites + 與 ndbcluster 相關的指令集
│ ├── default.push-valgrind # 分為 default suites(排除 rpl)+ ndb 相關 suites + group_replication suite
│ ├── mysql-8.0-stage.push # 在 default.push 基礎上,為 mysql-8.0-stage 擴充套件的測試用例,在merge到main分支前使用
│ ├── mysql-8.0-stage.push.basic # mysql-8.0-stage.push 的子集
│ ├── mysql-trunk-meb-itch.push # 檔案為空
# default.push 的超集,目的是在 push 到 main 分支前,提前發現問題。
│ ├── mysql-trunk-stage.push # 內容與 mysql-8.0-stage.push 一樣,在merge到main分支前使用
│ ├── mysql-trunk-stage.push.basic # mysql-trunk-stage.push 的子集
│ └── mysql-trunk-tsan.push # 由於 ThreadSanitizer 非常慢,因此,只測試 main suite
├── extra # 不屬於 main 和 其他 suites 的測試 case
│ ├── binlog_tests
│ │ ├── binlog.test
│ │ ├── binlog_cache_stat.test
│ │ ├── binlog_crash_safe_ddl.inc
│ │ ├── binlog_ddl.inc
......
│ │ └── tmp_table.test
│ └── rpl_tests
│ ├── binlog_transaction_compression.inc
│ ├── check_slave_delay.inc
......
│ └── type_conversions.test
├── lib # 測試框架相關依賴檔案,裡面主要是一些用perl實現的邏輯。
│ ├── My
│ │ ├── Config.pm
│ │ ├── ConfigFactory.pm
......
│ │ └── Test.pm
│ ├── mtr_cases.pm
......
├── lock_order_dependencies.txt # mysql-test-run.pl 讀取該檔案來控制加鎖順序,與 --lock-order 選項有關。該檔案非空。
# 在 mtr 執行對應工具期間,比如 asan,對應的 .supp 檔案用於指定需要跳過的測試用例。
#
# ASAN、LSAN、TSAN 出自谷歌的 Sanitizer 專案,包含了 ASAN、LSAN、MSAN、TSAN等記憶體、執行緒錯誤的檢測工具。
├── asan.supp # ASAN(Address-Sanitizier),記憶體錯誤檢測工具。早期是LLVM中的特性,後被加入GCC 4.8。
├── lsan.supp # LSAN(LeakSanitizer),記憶體漏失檢測工具,已整合在 ASAN(AddressSanitizer)中。
├── tsan.supp # TSAN(ThreadSanitizer),執行緒間資料競爭的檢測工具。
├── valgrind.supp # Valgrind 是一個工具集。整合了:
# Memcheck 記憶體錯誤檢測器。
# Cachegrind 快取和分支預測分析器。
# Callgrind 可生成快取分析器的呼叫圖。
# Helgrind 執行緒錯誤檢測器。
# DRD 也是執行緒錯誤檢測器。
# Massif 堆分析器,它可以幫助程式使用更少的記憶體。
# DHAT 一種不同型別的堆分析器。使用它可以瞭解塊壽命,塊利用率和佈局效率低下的問題。
├── mtr -> ./mysql-test-run.pl # mysql-test-run.pl 指令碼別名
├── mysql-stress-test.pl
├── mysql-test-run -> ./mysql-test-run.pl
├── mysql-test-run.dox
├── mysql-test-run.pl # mtr 入口檔案,測試框架核心邏輯
# include/ 目錄包含.inc 檔案,在測試用例中通過 source 命令引入,就像 C/C++ 的標頭檔案。建議將多次重複使用的測試語句整合到 .inc 檔案中。
├── include # include 下所有 *.inc 都會被 t/ 目錄下的 *.test 參照
│ ├── Load_data.inc
......
│ ├── json_lookup.inc
│ ├── keyring_tests
│ │ ├── binlog
│ │ │ ├── rpl_binlog_cache_encryption.inc
......
│ ├── keyring_udf_keyring_plugin_loaded.inc
......
│ └── year-engine.test
# t/ 和 r/ 目錄分別對應於 main suite 的測試 case 和 期望結果。
# 測試 case 以 .test 字尾結尾。
# 另外還有 .opt 字尾檔案,它裡面指定了MySQL的引數。某些測試用例會涉及重啟,在重啟時可能會變更 mysql 引數,可能會用 .opt 檔案中指定的引數。
├── t # 該目錄下的每個 *.test 都對應一個測試 case 。
│ ├── 1st.test
│ ├── admin_interface.test
......
├── r # 路徑和命名 與 t/ 目錄一一對應,表示對應測試用例的期望輸出。
│ ├── 1st.result
│ ├── admin_interface.result
......
│ └── year-myisam.result
├── std_data # 測試所用的資料檔案,某些測試 case 需要使用到。
│ ├── 14897.frm
│ ├── 256kb.json
│ ├── 41_decimal.frm
│ ├── 57import.zip
......
│ └── x_y_data.csv
# 測試框架有 suite 的概念,每個 suite 為一個測試用例集合,預設的 suite 為 main,它的測試集合位於當前目錄下的 t/ 目錄。
# 除了 main suite 之外,其他的 suite 基本都以子目錄的形式存放於當前資料夾,比如 json、binlog 等。
├── suite # 本目錄下每個子目錄都包含 include/r/t 三個子目錄,其中:
# include/*.inc 會被 t/*.test 參照
# t/*.test 是各個測試case的主檔案
# r/*.result 是期望的測試輸出
# 另外,t/ 與 r/ 路徑中的檔案是一一對應的。
│ ├── audit_null
......
│ ├── innodb
│ │ ├── include
│ │ │ ├── alter_table_pk_no_sort.inc
......
│ │ ├── r
│ │ │ ├── add_foreign_key.result
│ │ │ ├── alter_crash.result
......
│ │ └── t
│ │ ├── add_foreign_key.test
│ │ ├── alter_crash.test
......
│ │ └── zlob_update_purge.test
│ ├── innodb_fts
......
└── var # 測試開啟後 mtr 建立的目錄,用於存放測試過程產生的資料目錄、紀錄檔等。
├── data
│ ├── #ib_16384_0.dblwr
......
......
├── my.cnf
├── run
├── std_data
│ ├── 14897.frm
......
└── tmp
└── mysqld.1
參考:
--force
--max-test-fail=0
忽略計數。--max-test-fail
--record
.results
檔案,再基於該檔案修改成我們預期的結果。testname.result
檔案不同,會生成一個 testname.reject
檔案,該檔案在下次執行成功之後被刪除;.reject
檔案的內容,如果裡面是期望的輸出,則將內容拷貝到 .result
檔案中,作為以後判斷執行結果是否通過的依據;--parallel
—-nowarnings
--max-test-fail
。--big-test
big
的 test cases,也就是同時覆蓋 非 big + big。這是因為標記為 big 的 case 較大、耗時較長,預設不會執行。--only-big-test
:只啟用帶 big 標記的 test cases,也就是會跳過普通的非 big 標記的 cases。--suite=[suitename1,...]
./mtr --suite=rpl
只執行 rpl 測試集。--do-test=events
events
為字首的 case(搜尋範圍為 t/和所有的 suite)。--do-test
的引數支援正規表示式,上述命令等效於 ./mtr --do-test=events.*
./mtr --do-test=.*innodb.*
# --extern 一般情況下mtr是啟動自己的MySQL服務來進行測試,如果在啟動時指定引數 --extern,則可以使用指定的 MySQL 服務進行測試
./mtr --extern host=192.168.6.1 --extern port=3306 --extern user=root --extern password='123456' --record --force example.1
./mtr --extern host=127.0.0.1 --extern port=3306 --extern user=root --extern password= --force --max-test-fail=0 --suite=main
./mtr --extern host=127.0.0.1 --extern port=3306 --extern user=root --extern password= --force --max-test-fail=0 --fast --suite=main
--debug-server
:Use debug version of server, but without turning on tracing.--platform
和 --exclude-platform
:用於指定或排除平臺的選項。
PB2WORKDIR
,即export PB2WORKDIR=
),這兩個選項是不生效的。comment=STR
:新增該選項後,mtr 會將註釋資訊列印到 stdout 。比如 --comment=all-default-big
:##############################################################################
# all-default-big
##############################################################################
--vardir=DIR
:指定測試過程中生成的檔案存放的目錄,預設是當前路徑下的var/
。--report-features
:指定該選項後,mtr 首先執行名為 report_features
的 case,該 case 沒有任何輸出(設定了--disable_query_log
) 。--unit-tests-report
:加上該引數後,如果在編譯後的原始碼目錄執行 mtr,會在測試的最後階段加上每個測試用例的報告資訊。......
[----------] 1027 tests from Spec/ReuseConnectionTest (404 ms total)
[----------] Global test environment tear-down
[==========] 1027 tests from 1 test suite ran. (70804 ms total)
Total Test time (real) = 3363.87 sec
......
The following tests FAILED:
203 - routertest_component_metadata_ttl (Subprocess aborted)
206 - routertest_component_rest_api_enable (Failed)
222 - routertest_component_routing_splicer (Failed)
224 - routertest_integration_routing_reuse (Failed)
Errors while running CTest
[ FAILED ] CheckEdgeHttpsPortValues/UseEdgeHttpsPortValues.ensure_bootstrap_works_for_edge_https_port_values/1, where GetParam() = 65535 (1444 ms)
[ FAILED ] 1 test, listed below:
[ FAILED ] CheckEdgeHttpsPortValues/UseEdgeHttpsPortValues.ensure_bootstrap_works_for_edge_https_port_values/1, where GetParam() = 65535
1 FAILED TEST
[ FAILED ] Spec/SplicerFailParamTest.fails/client_ssl_dh_params_not_exists, where GetParam() = 64-byte object <C8-CE 3D-2F 4D-56 00-00 F0-DA BB-30 4D-56 00-00 B0-DB BB-30 4D-56 00-00 B0-DB BB-30 4D-56 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 3D-D1 F9-2E 4D-56 00-00 AD-D0 F9-2E 4D-56 00-00> (383 ms)
[ FAILED ] 1 test, listed below:
[ FAILED ] Spec/SplicerFailParamTest.fails/client_ssl_dh_params_not_exists, where GetParam() = 64-byte object <C8-CE 3D-2F 4D-56 00-00 F0-DA BB-30 4D-56 00-00 B0-DB BB-30 4D-56 00-00 B0-DB BB-30 4D-56 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 3D-D1 F9-2E 4D-56 00-00 AD-D0 F9-2E 4D-56 00-00>
1 FAILED TEST
[ FAILED ] 0 tests, listed below:
0 FAILED TESTS
[ FAILED ] Spec/ReuseConnectionTest: SetUpTestSuite or TearDownTestSuite
1 FAILED TEST SUITE
Unit tests: 98% tests passed, 4 tests failed out of 224
The following tests FAILED:
206 - routertest_component_rest_api_enable (Failed)
222 - routertest_component_routing_splicer (Failed)
224 - routertest_integration_routing_reuse (Failed)
Report from unit tests in /data/work/mysql/mysql-server/mysql-test/var-all-default-big/ctest.log
------------------------------------------------------------------------------
The servers were restarted 3 times
The servers were reinitialized 0 times
Spent 53.181 of 3579 seconds executing testcases
Completed: Failed 1/6 tests, 83.33% were successful.
Failing test(s): unit_tests
--no-skip
:指定該選項後,即使 .inc
檔案中要求的條件不滿足,也會執行所有的 mtr 測試 cases 。特別地,在 include/excludenoskip.list
檔案中指定的 .inc
檔案列表依然會跳過。--skip-ndb
:與選項--skip-ndbcluster
含義相同,表示跳過與 ndb 相關的 suites,預設啟用。
storage/ndb/
),涉及 ndb 引擎的 suites 包括:- ndb
- ndb_big
- ndb_opt
- ndb_ddl
- ndb_binlog
- ndb_rpl
- rpl_ndb
- ndbcluster
- gcol_ndb
- json_ndb
--with-ndb-only
:與選項--with-ndbcluster-only
含義相同,只執行與 ndb 相關的 suites 。如果沒顯示指定--suites
引數,則會跳過所有非 ndb 的 suites ;反之,若指定了,也會額外執行指定的 suites 。--ps-protocol
:在 client 和 server 端之間使用 prepared-statement 協定(binary),會將--ps-protocol
引數直接傳給 mysqltest 程式。--skip-combinations
:忽略組合檔案或選項,也就是忽略:# 啟動 mtr 時的紀錄檔:
Collecting tests
- Adding combinations for binlog
- Adding combinations for binlog_gtid
- Adding combinations for binlog_nogtid
- Adding combinations for rpl
- Adding combinations for rpl_gtid
- Adding combinations for rpl_nogtid
# 對應於
./suite/rpl_nogtid/combinations
./suite/binlog_gtid/combinations
./suite/binlog/combinations
./suite/rpl/combinations
./suite/rpl_gtid/combinations
./suite/binlog_nogtid/combinations
# 除此之外,還有:
./suite/ndb_rpl/t/ndb_rpl_innodb2ndb.combinations
./suite/ndb_rpl/t/ndb_rpl_conflict_epoch.combinations
./suite/ndb_rpl/t/ndb_rpl_basic.combinations
main,
audit_null,
auth_sec,
binlog,
binlog_gtid,
binlog_nogtid,
clone,
collations,
component_keyring_file,
connection_control,
encryption,
engines,
engines/funcs,
engines/iuds,
engines/rr_trx,
federated,
funcs_1, # 額外功能(包括檢視、儲存過程、INFORMATION_SCHEMA等)
funcs_2, # 額外功能(字元集等)
gcol, # 虛擬生成列
gis,
group_replication,
information_schema,
innodb,
innodb_fts, # 全文索引
innodb_gis,
innodb_stress,
innodb_undo,
innodb_zip,
interactive_utilities,
jp, # 日語字元集
json,
large_tests,
lock_order,
max_parts,
memcached,
network_namespace,
opt_trace,
parts,parts/special_tests,
perfschema,
query_rewrite_plugins,
rpl,
rpl_gtid,
rpl_nogtid,
secondary_engine,
service_status_var_registration,
service_sys_var_registration,
service_udf_registration,
special,
stress,
sys_vars,
sysschema,
test_service_sql_api,
test_services,
x
auth_sec,binlog,binlog_gtid,binlog_nogtid,clone,
collations,component_keyring_file,connection_control,encryption,
federated,funcs_2,gcol,gis,information_schema,
innodb,innodb_fts,innodb_gis,innodb_undo,innodb_zip,
interactive_utilities,json,
main,
opt_trace,parts,perfschema,query_rewrite_plugins,rpl,rpl_gtid,rpl_nogtid,secondary_engine,
service_status_var_registration,service_sys_var_registration,service_udf_registration,
sys_vars,sysschema,test_service_sql_api,test_services,x
funcs_2, stress, jp, nist
engines, memcached, audit_null
group_replication
編譯的原始碼目錄/mysql-test
執行。編譯的原始碼目錄/mysql-test
和 安裝目錄/mysql-test
都可以執行。.result
檔案的情況下,可先通過--reocrd
選項生成.result
檔案,再基於該檔案修改成期望的結果:perl mysql-test-run.pl --record mytest
--reocrd
選項,這樣才會比對實際結果與期望結果是否相同:perl mysql-test-run.pl mytestcase1
perl mysql-test-run.pl --suites=main,rpl # 指定多個 suites
./mtr testcasename --record
# 只執行基礎套餐裡的 subquery_all 用例( t/subquery_all.test )
# 可選 --charset-for-testdb=utf8mb4
./mtr --force --big-test --nowarnings --max-test-fail=0 main.subquery_all
# 如需執行多個 case,可通過空格分割,比如:
./mtr --force --big-test --nowarnings --max-test-fail=0 main.subquery_all main.myisam_explain_json_non_select_none
./mtr --force
mysql-test/t/*.test
),忽略中間的 warnings 報錯,強制執行完所有 case:./mtr --suite=main --force --max-test-fail=0 --nowarnings --parallel=8
./mtr --suite=main --force --max-test-fail=0 --nowarnings --parallel=8 --big-test
events
為字首的 case,搜尋範圍為 mysql-test/t
、mysql-test/suite
,注意不包括extra/
:# --do-test 引數支援正規表示式,該指令等效於./mtr --do-test=events.*
./mtr --do-test=events --force --max-test-fail=0
# 如果想測試所有包含 innodb 的 case,可以用 ./mtr --do-test=.*innodb.*
1、準備資料庫: create database test
。
a)執行 ./mtr --extern host=127.0.0.1 --extern port=3306 --extern user=root --extern password= --force --max-test-fail=0 --suite=main
,第一個非 skipped case 可以執行成功,但之後的 case 全部失敗。
b)分析原因,發現是每執行完一個 case ,mtr 就會 shutdown mysqld server,下一個 case 再啟動,而這裡是使用的外部 mysql,則不會啟動。
2、檢視手冊,發現有一個引數可以控制是否每個 case 都重啟 mysqld:
--fast
Do not perform controlled shutdown when servers need to be restarted or at the end of the test run. This is equivalent to using --shutdown-timeout=0.
Note
If a test case has an .opt file that requires the server to be restarted with specific options, the
file will not be used. The test case likely will fail as a result.
可見,官方對這種用法的支援尚不完善。
如果需要驗證 release 版本穩定性(適用於 QA、研發),可參考 default.daily
中的指令集。
我們通過一個最簡單的例子來說明這個框架是怎麼使用的。
在 mysql-test/t
目錄下建立一個檔名為 mytest.test
的測試用例:
--disable_warnings
DROP TABLE IF EXISTS t1;
SET @@sql_mode='NO_ENGINE_SUBSTITUTION';
--enable_warnings
SET SQL_WARNINGS=1;
--echo #
--echo # test content
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);
SELECT * FROM t1;
DROP TABLE t1;
在mysql-test/r
目錄下建立名為mytest.result
的檔案:
DROP TABLE IF EXISTS t1;
SET @@sql_mode='NO_ENGINE_SUBSTITUTION';
SET SQL_WARNINGS=1;
#
# test content
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);
SELECT * FROM t1;
a
1
2
DROP TABLE t1;
可見,.result
檔案中不僅要記錄 SQL,還要記錄輸出結果。
指令:
cd mysql80-debug/mysql-test
./mtr main.mytest
輸出:
Logging: ./mtr main.mytest
MySQL Version 8.0.29
Checking supported features
- Binaries are debug compiled
Using 'all' suites
Collecting tests
Checking leftover processes
Removing old var directory
Creating var directory '/Users/wslu/work/mysql/mysql80-debug/mysql-test/var'
Installing system database
Using parallel: 1
==============================================================================
TEST NAME RESULT TIME (ms) COMMENT
------------------------------------------------------------------------------
[ 50%] main.mytest [ pass ] 63
[100%] shutdown_report [ pass ]
------------------------------------------------------------------------------
The servers were restarted 0 times
The servers were reinitialized 0 times
Spent 0.063 of 16 seconds executing testcases
Completed: All 2 tests were successful.
看到 successful 說明執行成功。
在 mytest.result
檔案中新增一些字元:
DROP TABLE IF EXISTS t1;
SET @@sql_mode='NO_ENGINE_SUBSTITUTION';
SET SQL_WARNINGS=1;
#
# test content
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);
SELECT * FROM t1; # new comment
a
1
2
DROP TABLE t1;
再次執行指令./mtr main.mytest
,可見# new comment
那一行報錯:
==============================================================================
TEST NAME RESULT TIME (ms) COMMENT
------------------------------------------------------------------------------
[ 50%] main.mytest [ fail ]
Test ended at 2023-03-20 15:07:50
CURRENT_TEST: main.mytest
--- /Users/wslu/work/mysql/mysql80-debug.bak_asan_ubsan_gcov/mysql-test/r/mytest.result 2023-03-20 10:07:31.000000000 +0300
+++ /Users/wslu/work/mysql/mysql80-debug.bak_asan_ubsan_gcov/mysql-test/var/log/mytest.reject 2023-03-20 10:07:50.000000000 +0300
@@ -7,7 +7,7 @@
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);
-SELECT * FROM t1; # new comment
+SELECT * FROM t1;
a
1
2
mysqltest: Result length mismatch
The result from queries just before the failure was:
DROP TABLE IF EXISTS t1;
SET @@sql_mode='NO_ENGINE_SUBSTITUTION';
SET SQL_WARNINGS=1;
#
# test content
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);
SELECT * FROM t1;
a
1
2
DROP TABLE t1;
safe_process[19130]: Child process: 19131, exit: 1
- the logfile can be found in '/Users/wslu/work/mysql/mysql80-debug.bak_asan_ubsan_gcov/mysql-test/var/log/main.mytest/mytest.log'
[100%] shutdown_report [ pass ]
------------------------------------------------------------------------------
mtr 會指出具體是哪行導致的 case 失敗。
mysql-test/t/select_all.test
這個測試 case,其預期結果在mysql-test/r/select_all.result
,在實際執行時,會將執行結果與mysql-test/r/select_all.result
作比較,若不一致,則失敗,並在mysql-test/var/log
目錄生成一個.reject
檔案。此外,測試用例可以執行外部程式,因此在某些方面,測試框架可以擴充套件為測試 SQL 語句以外的用途。
最後,可以在測試中嵌入一小段 Perl 程式碼。這有時可用於執行超出測試語言或 SQL 能力的操作或執行邏輯。
可使用一些技巧來定為具體的錯誤原因,詳見下節。
預設情況下,在目錄 mysql-test/var/log/
中有紀錄檔生成(若指定 --vardir
引數,則以該引數路徑為準),分析該紀錄檔也能得到一些有用資訊。
比如 啟動失敗,則可以檢視 bootstrap.log
檔案,去掉命令中的 --bootstrap
並執行即可啟動對應的 MySQL 服務來驗證、偵錯。
啟動 mtr 時加 --verbose
引數,定位到參照的指令碼位置後可以設定 --echo
命令修改偵錯。
如果加上 --verbose
列印的內容還不夠詳細,可以再加一個,即 --verbose --verbose
,能列印出 mtr perl 指令碼中的紀錄檔資訊。
範例:
wslu@ubuntu:/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test$ perl mysql-test-run.pl --timer --force --parallel=1 --vardir=var-rpl --suite=rpl --verbose
Logging: mysql-test-run.pl --timer --force --parallel=1 --vardir=var-rpl --suite=rpl --verbose
> exe_name: mysqld
MySQL Version 8.0.29
Checking supported features
- Binaries are debug compiled
> Testing FIPS: --test-ssl-fips-mode 0 error:0F06D065:common libcrypto routines:FIPS_mode_set:fips mode not supported
Using suite(s): rpl
Collecting tests
> Collecting: rpl
> suitedir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl
> testdir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl/t
> resdir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl/r
> Read combinations file /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl/combinations.
- Adding combinations for rpl
> Collecting: i_rpl
Removing old var directory
> opt_vardir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl
> Removing /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var
> Removing /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/
> Removing /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/
Creating var directory '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl'
> Creating /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl
Installing system database
### safe_path: /data/work/mysql/mysql80-install.bak_asan_ubsan/bin//mysqltest_safe_process --verbose -- /data/work/mysql/mysql80-install.bak_asan_ubsan/bin/mysqld --no-defaults --initialize-insecure --loose-skip-ndbcluster --tmpdir=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/ --core-file --datadir=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/data/ --secure-file-priv=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl --innodb_buffer_pool_size=24M --innodb-log-file-size=5M --innodb_autoextend_increment=8 --character-sets-dir=/data/work/mysql/mysql80-install.bak_asan_ubsan/share/charsets --loose-auto_generate_certs=OFF --loose-sha256_password_auto_generate_rsa_keys=OFF --loose-caching_sha2_password_auto_generate_rsa_keys=OFF --init-file=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/bootstrap.sql
Using parallel: 1
==============================================================================
TEST NAME RESULT TIME (ms) COMMENT
------------------------------------------------------------------------------
> Client connected
worker[1] > mtr_ping_port: 13000
worker[1] > FREE
worker[1] > mtr_ping_port: 13001
worker[1] > FREE
worker[1] > mtr_ping_port: 13002
worker[1] > FREE
worker[1] > mtr_ping_port: 13003
worker[1] > FREE
......
worker[1] > mtr_ping_port: 13029
worker[1] > FREE
worker[1] > Using MTR_BUILD_THREAD 300, with reserved ports 13000..13029
worker[1] Creating var directory '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl'
worker[1] > result: , file_mode: 0
[ 0%] rpl.rpl_atomic_ddl [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_atomic_ddl_no_binlog [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_binlog_cache_encryption [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_filters_error_cases_on_startup [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_group_commit_deadlock [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_group_commit_deadlock_myisam [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_innodb_auto_increment [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_killed_ddl [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_log_info_repository_persistence_assign_gtids_to_anonymous_transactions [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_log_info_repository_persistence_require_row [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_log_info_repository_persistence_require_table_primary_key_check [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_row_crash_safe [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_row_mts_rec_crash_safe [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_stm_mixed_crash_safe [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_stm_mixed_mts_rec_crash_safe [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_stm_mixed_mts_rec_crash_safe_checksum [ skipped ] Test needs 'big-test' or 'only-big-test' option.
[ 0%] rpl.rpl_io_thd_wait_for_disk_space_stress [ disabled ] BUG#23581287 Disabled until bug is fixed.
[ 0%] rpl.rpl_writeset_add_unique_key [ disabled ] Bug#33134835 RPL_WRITESET_ADD_UNIQUE_KEY FAILS SPORADICALLY
worker[1] > Running test: rpl.rpl_plugin_load
worker[1] > Setting timezone: GMT-3
worker[1] > Cleaning datadirs...
worker[1] > clean_dir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp
worker[1] > unlink: '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/bootstrap.sql'
worker[1] > Generating my.cnf from '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl/my.cnf'
worker[1] > MASTER_MYPORT = 13000
worker[1] > MASTER_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqld.1.sock
worker[1] > MASTER_X_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqlx.1.sock
worker[1] > SLAVE_MYPORT = 13002
worker[1] > SLAVE_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqld.2.sock
worker[1] > SLAVE_X_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqlx.2.sock
worker[1] > mysqld_start: [' --plugin-dir=/data/work/mysql/mysql80-install.bak_asan_ubsan/lib/plugin', '--binlog-format=mixed ']
### safe_path: /data/work/mysql/mysql80-install.bak_asan_ubsan/bin//mysqltest_safe_process --verbose -- /data/work/mysql/mysql80-install.bak_asan_ubsan/bin/mysqld --defaults-group-suffix=.1 --defaults-file=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/my.cnf --log-output=file --loose-debug-sync-timeout=600 --plugin-dir=/data/work/mysql/mysql80-install.bak_asan_ubsan/lib/plugin --binlog-format=mixed --core-file
worker[1] > Started [mysqld.1 - pid: 61921, winpid: 61921]
worker[1] > mysqld_start: [' --plugin-dir=/data/work/mysql/mysql80-install.bak_asan_ubsan/lib/plugin', '--binlog-format=mixed ']
......
mtr 支援的一些 debug 引數:
debug Dump trace output for all servers and client programs.
debug-common Same as debug, but sets 'd' debug flags to
"query,info,error,enter,exit"; you need this if you
want both to see debug printouts and to use
DBUG_EXECUTE_IF.
debug-server Use debug version of server, but without turning on
tracing.
debugger=NAME Start mysqld in the selected debugger.
gdb Start the mysqld(s) in gdb.
lldb Start the mysqld(s) in lldb.
可見,要想跟蹤呼叫過程,只有 --debug
和 --gdb
引數滿足要求,會生成 trace 資訊。
範例:
# 這幾條指令很耗費記憶體
./mtr --debug --suite=rpl
./mtr --gdb --suite=rpl
./mtr --debug --gdb --suite=rpl
指令執行後,生成 trace 檔案,比如 var/log/bootstrap.trace
。
如果參照(source
)的指令碼支援 debug 引數,比如常用的 $rpl_debug
,則可以修改相應的 .inc
檔案以獲得更多的 debug 資訊。
新增-d
引數可進入 perl 語言的 debug 模式,便於偵錯 mysql-test-run.pl
及其呼叫。範例:
wslu@ubuntu:/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test$ perl -d mysql-test-run.pl --timer --force --parallel=1 --vardir=var-rpl --suite=rpl
Loading DB routines from perl5db.pl version 1.60
Editor support available.
Enter h or 'h h' for help, or 'man perldebug' for more help.
main::(mysql-test-run.pl:54): push @INC, ".";
DB<1> l
54==> push @INC, ".";
55
56: use My::ConfigFactory;
57: use My::CoreDump;
58: use My::File::Path; # Patched version of File::Path
59: use My::Find;
60: use My::Options;
61: use My::Platform;
62: use My::SafeProcess;
63: use My::SysInfo;
DB<1> n
main::(mysql-test-run.pl:72): require "lib/mtr_gcov.pl";
DB<1> l
72==> require "lib/mtr_gcov.pl";
73: require "lib/mtr_gprof.pl";
74: require "lib/mtr_io.pl";
75: require "lib/mtr_lock_order.pl";
76: require "lib/mtr_misc.pl";
77: require "lib/mtr_process.pl";
78
79: our $secondary_engine_support = eval 'use mtr_secondary_engine; 1';
80
81 # Global variable to keep track of completed test cases
DB<1>
偵錯模式常用命令:
h 檢視幫助檔案
c line 執行到指定行
n 執行到下一行
s 跳到函數內部執行
l 檢視程式碼
q 退出
歡迎關注我的微信公眾號【資料庫核心】:分享主流開源資料庫和儲存引擎相關技術。
標題 | 網址 |
---|---|
GitHub | https://dbkernel.github.io |
知乎 | https://www.zhihu.com/people/dbkernel/posts |
思否(SegmentFault) | https://segmentfault.com/u/dbkernel |
掘金 | https://juejin.im/user/5e9d3ed251882538083fed1f/posts |
CSDN | https://blog.csdn.net/dbkernel |
部落格園(cnblogs) | https://www.cnblogs.com/dbkernel |