- GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯系小編并注明來源,
- GreatSQL是MySQL的國產分支版本,使用上與MySQL一致,
- 作者: Yejinrong/葉金榮
- 文章來源:GreatSQL社區投稿
-
- 編譯GreatSQL
-
- 安裝gdb
-
- 開始除錯GreatSQL原始碼
- 3.1 利用gdb設定斷點
- 3.2 使用 Trace 檔案除錯
有時為了跟蹤故障需要除錯MySQL/GreatSQL原始碼,本文介紹如何在Linux下構建MySQL/GreatSQL原始碼除錯環境,
在這之前,我也是一名小白,一起從零開始探索吧,
本文以CentOS 8.x環境下的GreatSQL 8.0.25-16版本為例,
1. 編譯GreatSQL
查看系統環境:
$ cat /etc/system-release
CentOS Linux release 8.4.2105
首先,從https://gitee.com/GreatSQL/GreatSQL/releases/ 下載GreatSQL 8.0.25-16的原始碼包
- Source Code
Packages Size greatsql-8.0.25-16.tar.gz 503M
接下來,參考文章 在Linux下原始碼編譯安裝GreatSQL 構建好編譯環境,然后開始編譯GreatSQL原始碼,編譯引數中增加/修改debug相關選項,這樣編譯后得到的二進制檔案才能支持除錯模式,例如:
$ cd /opt/greatsql-8.0.25-16
$ mkdir -p build
$ cd build
$ cmake3 .. \
-DBOOST_INCLUDE_DIR=/opt/boost_73_0 \
-DLOCAL_BOOST_DIR=/opt/boost_73_0 \
-DCMAKE_INSTALL_PREFIX=/usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64 \
-DWITH_ZLIB=bundled \
-DWITH_NUMA=ON \
-DCMAKE_EXE_LINKER_FLAGS="-ljemalloc" \
-DBUILD_CONFIG=mysql_release \
-DWITH_TOKUDB=OFF \
-DWITH_ROCKSDB=OFF \
-DMAJOR_VERSION=8 \
-DMINOR_VERSION=0 \
-DPATCH_VERSION=25 \
-DWITH_UNIT_TESTS=OFF \
-DWITH_NDBCLUSTER=OFF \
-DWITH_SSL=system \
-DWITH_SYSTEMD=ON \
-DWITH_LDAP=OFF \
-DWITH_AUTHENTICATION_LDAP=OFF \
-DWITH_DEBUG=1 \
-DCMAKE_BUILD_TYPE=Debug \
&& make -j8 VERBOSE=1 && make install
主要是增加兩個引數 -DWITH_DEBUG=1 和 -DCMAKE_BUILD_TYPE=Debug,注意不要有引數 -DCMAKE_BUILD_TYPE=RelWithDebInfo,
編譯完成后,即可得到包含debug功能的GreatSQL二進制檔案,執行下面的命令檢查:
$ cd /usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64
$ ./bin/mysqld-debug --verbose --version
/usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64/bin/mysqld-debug Ver 8.0.25-16-debug for Linux on x86_64 (Source distribution)
可以看到,輸出的結果中包含 debug 關鍵字,這就表示成功了,
2. 安裝gdb
直接執行yum安裝gdb即可:
$ yum install -y gdb
$ gdb --version
GNU gdb (GDB) Red Hat Enterprise Linux 9.2-4.el8
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
gdb常用的除錯相關指令有以下幾個:
| 命令 | 縮寫 | 備注 |
|---|---|---|
| attach | 掛接/進入準備除錯的行程pid | |
| detach | 取消掛接行程(退出行程) | |
| list | l | 顯示多行源代碼 |
| break | b | 設定斷點,程式運行到斷點的位置會停下來 |
| info | i | 描述程式的狀態 |
| run | r | 開始運行程式 |
| display | disp | 跟蹤查看某個變數,每次停下來都顯示它的值 |
| step | s | 執行下一條陳述句,如果該陳述句為函式呼叫,則進入函式執行其中的第一條陳述句 |
| next | n | 執行下一條陳述句,如果該陳述句為函式呼叫,不會進入函式內部執行(即不會一步步地除錯函式內部陳述句) |
| p | 列印內部變數值 | |
| continue | c | 繼續程式的運行,直到遇到下一個斷點 |
| set var name=v | 設定變數的值 | |
| start | st | 開始執行程式,在main函式的第一條陳述句前面停下來 |
| file | 裝入需要除錯的程式 | |
| kill | k | 終止正在除錯的程式 |
| watch | 監視變數值的變化 | |
| backtrace | bt | 查看函式呼叫資訊(堆疊) |
| frame | f | 查看堆疊幀 |
| quit | q | 退出gdb |
3. 開始除錯GreatSQL原始碼
第一次運行gdb準備除錯時,可能會提示類似下面的資訊
warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
0x00007ffb358ada41 in poll () from /lib64/libc.so.6
Missing separate debuginfos, use: dnf debuginfo-install keyutils-libs-1.5.10-9.el8.x86_64 ...
這表示缺少一些相關的debuginfo包,可以根據提示內容補充安裝,例如:
dnf debuginfo-install keyutils-libs-1.5.10-9.el8.x86_64 ...
如果提示找不到這些安裝包:
Could not find debuginfo package for the following installed packages: keyutils-libs-1.5.10-9.el8.x86_64 ...
可以檢查yum組態檔 /etc/yum.repos.d/CentOS-Linux-Debuginfo.repo,確認是否設定了 enable = 1,例如:
# CentOS-Linux-Debuginfo.repo
#
# All debug packages are merged into a single repo, split by basearch, and are
# not signed.
[debuginfo]
name=CentOS Linux $releasever - Debuginfo
baseurl=http://debuginfo.centos.org/$releasever/$basearch/
gpgcheck=1
enabled=1 #<---這里要設定1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
此外,還要把GreatSQL 8.0.25-16的原始碼包解壓縮到 /opt 目錄下:
$ tar zxf PATH/greatsql-8.0.25-16.tar.gz -C /opt/
接下來,演示如何跟蹤除錯,
先初始化GreatSQL資料檔案,然后再啟動GreatSQL服務行程:
# 初始化GreatSQL
$ cd /usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64
$ ./bin/mysqld-debug --no-defaults --initialize-insecure --user=mysql --datadir=./data
# 啟動GreatSQL
$ ./bin/mysqld-debug --no-defaults --user=mysql --datadir=./data1 &
# 查看行程pid
$ ps -ef | grep mysqld
...
mysql 2644322 2542442 3 14:38 pts/7 00:00:01 ./bin/mysqld-debug --no-defaults --user=mysql --datadir=./data1
# 在另一個終端(終端#2),連入GreatSQL
$ mysql -S/tmp/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 8.0.25-16-debug Source distribution
...
mysql>\s
...
Server version: 8.0.25-16-debug Source distribution
...
啟動gdb,準備除錯跟蹤GreatSQL,我們分別演示幾種不同方式,
3.1 利用gdb設定斷點
在 終端#1 中啟動gdb,并掛接GreatSQL行程,準備跟蹤
$ gdb -p 2644322
GNU gdb (GDB) Red Hat Enterprise Linux 9.2-4.el8
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
...
Attaching to process 2644322
[New LWP 2643482]
[New LWP 2643483]
[New LWP 2643484]
...
[New LWP 2643522]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
--Type <RET> for more, q to quit, c to continue without paging-- #<-- 這里按下回車,即可進入
0x00007fb7ae93ba41 in __GI___poll (fds=0x7fb7ae229140, nfds=2, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
29 return SYSCALL_CANCEL (poll, fds, nfds, timeout);
(gdb)
(gdb) p mysql_sysvar_version #<-- 列印變數,查看GreatSQL版本號
$1 = {flags = 68101, name = 0x7f10d1c6cc90 "innodb_version", comment = 0x6c47f92 "InnoDB version", check = 0x37dd9e2
<check_func_str(THD*, SYS_VAR*, void*, st_mysql_value*)>, update = 0x37ddeb0 <update_func_str(THD*, SYS_VAR*, void*, void const*)>,
value = https://www.cnblogs.com/greatsql/archive/2023/04/11/0x7e7c768 , def_val = 0x6c38440"8.0.25-15"}
(gdb)
(gdb)
(gdb) b mysql_execute_command #<--- 輸入指令"b dispatch_command"設定斷點,意為當GreatSQL程式運行到這個函式時,就會停下來
Breakpoint 3 at 0x379c3f2: file /opt/greatsql-8.0.25-16/sql/sql_parse.cc, line 2875.
(gdb)
切換到 終端#2,隨便執行一條SQL命令:
mysql> select 'debug' from dual;
回到 終端#1,繼續除錯:
(gdb)
(gdb) bt #<-- 列印函式呼叫資訊
#0 dispatch_command (thd=0x7f10a3a0b000, com_data=https://www.cnblogs.com/greatsql/archive/2023/04/11/0x7f10d12a7370, command=COM_QUERY) at /opt/greatsql-8.0.25-16/sql/sql_parse.cc:1605
#1 0x0000000003797c48 in do_command (thd=0x7f10a3a0b000) at /opt/greatsql-8.0.25-16/sql/sql_parse.cc:1388
#2 0x0000000003991168 in handle_connection (arg=0x7f10d1f9d120) at /opt/greatsql-8.0.25-16/sql/conn_handler/connection_handler_per_thread.cc:307
#3 0x00000000052e4b22 in pfs_spawn_thread (arg=0x7f10e8a45660) at /opt/greatsql-8.0.25-16/storage/perfschema/pfs.cc:2899
#4 0x00007f10eb1e917a in start_thread (arg=) at pthread_create.c:479
#5 0x00007f10e9128dc3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb)
(gdb) p thd->m_query_string #<-- 列印SQL陳述句
$14 = {str = 0x7f10a3a0e828"select 'debug' from dual", length = 24}
(gdb)
(gdb) c #<-- 繼續執行,終端#2里被阻塞的SQL陳述句就可以執行了
Continuing.
切回 終端#2 查看SQL陳述句執行結果:
mysql> select 'debug' from dual;
+-------+
| debug |
+-------+
| debug |
+-------+
1 row in set (12 min 11.55 sec)
可以看到,因為一直被阻塞,這條SQL請求耗時超過12分鐘,當 終端#2 的連接斷開退出后,可以看到gdb端也有相應提示:
Thread 39 "mysqld-debug" hit Breakpoint 1, dispatch_command (thd=0x7f10a3a0b000, com_data=https://www.cnblogs.com/greatsql/archive/2023/04/11/0x7f10d12a7370, command=COM_QUIT)
at /opt/greatsql-8.0.25-16/sql/sql_parse.cc:1605
1605 bool error = false;
(gdb)
如果不想繼續跟蹤除錯了,只需輸入指令 q 或 quit 即可退出gdb,
(gdb) quit
A debugging session is active.
Inferior 1 [process 2644322] will be detached.
Quit anyway? (y or n) y
Detaching from program: /usr/local/GreatSQL-8.0.25-16-Linux-glibc2.28-x86_64/bin/mysqld-debug, process 2644322
[Inferior 1 (process 2644322) detached]
3.2 使用 Trace 檔案除錯
還可以在GreatSQL客戶端中設定變數 debug 為不同值,就可以輸出GreatSQL運行程序中涉及的呼叫模塊、函式、狀態資訊等全部資訊,并記錄到本地檔案中,用法示例:
mysql> SET SESSION debug = 'debug_options';
變數 debug 支持多種設定模式:
debug_options = field_1:field_2:...:field_N
field = [+|-]flag[,modifier,modifier,...,modifier]
+, - 表示從當前debug值添加或者減少某些選項,
flag相關可選項如下:
| flag | 說明 |
|---|---|
| d | 開啟DBUG |
| f | 只跟蹤指定的函式 |
| F | 跟蹤指定的原始碼檔案 |
| i | 跟蹤指定的執行緒 |
| L | 跟蹤指定的原始碼行數 |
| n | 列印函式呼叫層次序號 |
| N | 輸出日志從0開始列印行號 |
| o | 指定輸出到某個檔案 |
| O | 類似o,每次寫檔案都會flush,reopen |
| P | 匹配DBUG_PROCESS |
| p | 列印process name |
| t | 列印函式呼叫和退出 |
使用案例1(精簡模式)
# 設定debug選項
mysql> set session debug='d:t:o,/tmp/mysqld.trace';
# 執行SQL請求
mysql> select 'debug' from dual;
+-------+
| debug |
+-------+
| debug |
+-------+
1 row in set (0.00 sec)
查看生成的trace檔案:
$ cat /tmp/mysqld.trace
...
>do_command
| >THD::clear_error
| <THD::clear_error
| >Diagnostics_area::reset_diagnostics_area
| <Diagnostics_area::reset_diagnostics_area
| >my_net_set_read_timeout
| | enter: timeout: 28800
| | >vio_socket_timeout
| | <vio_socket_timeout
| <my_net_set_read_timeout
| >vio_is_blocking
| <vio_is_blocking
| >net_read_raw_loop
| | >vio_read
| | | >vio_is_blocking
| | | <vio_is_blocking
| | | >vio_io_wait
| | | <vio_io_wait
| | <vio_read
| <net_read_raw_loop
| THD::enter_stage: 'starting' /opt/greatsql-8.0.25-16/sql/conn_handler/init_net_server_extension.cc:102
...
使用案例2(復雜模式)增加了列印檔案名和行號等資訊,更方便定位查找,
mysql> set session debug='d:t:L:F:o,/tmp/mysqld.trace';
mysql> select 'debug' from dual;
...
查看生成的trace檔案:
$ cat /tmp/mysqld.trace
...
sql_parse.cc: <do_command
sql_parse.cc: 1269: >do_command
sql_class.h: 3287: | >THD::clear_error
sql_class.h: | <THD::clear_error
sql_error.cc: 357: | >Diagnostics_area::reset_diagnostics_area
sql_error.cc: | <Diagnostics_area::reset_diagnostics_area
net_serv.cc: 2246: | >my_net_set_read_timeout
net_serv.cc: 2247: | | enter: timeout: 28800
viosocket.cc: 380: | | >vio_socket_timeout
viosocket.cc: | | <vio_socket_timeout
net_serv.cc: | <my_net_set_read_timeout
viosocket.cc: 373: | >vio_is_blocking
viosocket.cc: | <vio_is_blocking
net_serv.cc: 1341: | >net_read_raw_loop
viosocket.cc: 169: | | >vio_read
viosocket.cc: 373: | | | >vio_is_blocking
viosocket.cc: | | | <vio_is_blocking
viosocket.cc: 1118: | | | >vio_io_wait
viosocket.cc: | | | <vio_io_wait
viosocket.cc: | | <vio_read
net_serv.cc: | <net_read_raw_loop
sql_parse.cc: 320: | THD::enter_stage: 'starting' /opt/greatsql-8.0.25-16/sql/conn_handler/init_net_server_extension.cc:102
...
本文簡單演示了如何跟蹤除錯GreatSQL的幾種方法,更多有趣實用的方法還有待進一步挖掘,一起探索新世界吧,
P.S,我也在MacOS環境下構建了基于vscode的跟蹤除錯環境,但還是更喜歡在Linux終端命令列模式下作業,所以本文沒介紹如何利用vscode跟蹤除錯,有興趣的讀者可以根據其他資料自行構建,
Enjoy GreatSQL ??
關于 GreatSQL
GreatSQL是由萬里資料庫維護的MySQL分支,專注于提升MGR可靠性及性能,支持InnoDB并行查詢特性,是適用于金融級應用的MySQL分支版本,
相關鏈接: GreatSQL社區 Gitee GitHub Bilibili
GreatSQL社區:
社區博客有獎征稿詳情:https://greatsql.cn/thread-100-1-1.html

技術交流群:
微信:掃碼添加
GreatSQL社區助手微信好友,發送驗證資訊加群,

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/549799.html
標籤:其他
下一篇:flume基本安裝與使用
