從零開始學習MySQL調試跟蹤(1)

来源:https://www.cnblogs.com/greatsql/archive/2023/04/11/17306368.html
-Advertisement-
Play Games

GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。 GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。 作者: Yejinrong/葉金榮 文章來源:GreatSQL社區投稿 編譯GreatSQL 安裝gdb 開始調試GreatSQL源碼 3.1 利用gd ...


  • GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。
  • GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。
  • 作者: Yejinrong/葉金榮
  • 文章來源:GreatSQL社區投稿

    1. 編譯GreatSQL
    1. 安裝gdb
    1. 開始調試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的源碼包

  1. 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 執行下一條語句,如果該語句為函數調用,不會進入函數內部執行(即不會一步步地調試函數內部語句)
print 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 = 0x7e7c768 <innodb_version_str>, 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=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=<optimized out>) 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=0x7f10d12a7370, command=COM_QUIT)
    at /opt/greatsql-8.0.25-16/sql/sql_parse.cc:1605
1605      bool error = false;
(gdb)

如果不想繼續跟蹤調試了,只需輸入指令 qquit 即可退出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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在Linux系統中,執行一個程式或命令就可以觸發一個進程,系統會給予這個進程一個ID,稱為PID,同時根據觸發這個進程的用戶與相關屬性關係,基於這個PID一組有效的許可權設置。舉個常見的例子,我們要操作系統的時候通常是利用ssh連接程式或直接在主機上登錄,然後獲取shell。預設的shell是bash... ...
  • 文章原鏈接:http://t.csdn.cn/x3yDi 一、CentOS7查看開放埠命令 CentOS7的開放關閉查看埠都是用防火牆來控制的,具體命令如下: 查看已經開放的埠 firewall-cmd --list-ports 開啟埠 firewall-cmd --zone=public ...
  • 在一些實際的場景里,我們需要通過利用一些埠轉發工具,比如系統自帶的命令行工具或第三方小軟體,來繞過網路訪問限制觸及目標系統。下文為大家總結了linux系統和windows系統埠轉發常用的一些方法。 ...
  • 在AIX系統中,查看網卡配置可以使用entstat和lsdev命令來實現。 使用entstat命令查看網卡配置 使用以下命令查看所有網卡的信息: entstat -all 使用以下命令查看指定網卡的信息: entstat -d enX 其中enX代表網卡的名稱,例如en0表示第一塊網卡,en1表示第 ...
  • GPFS 文件系統部署步驟 參考文檔: 簡書網友提供: https://www.jianshu.com/p/a0ecc0838b3b?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendat ...
  • 首先可以直接改Hosts文件(現在不太管用了)。如果你是Linux或Mac系統,那麼可以通過命令sudo vim /etc/hosts打開Hosts文件併進行修改。如果你已經擁有了網路代理服務,那麼我們可以在此基礎上配置終端代理。我們查看得知自己代理伺服器的IP地址為http://127.0.0.1... ...
  • 鎖屏面試題百日百刷,每個工作日堅持更新面試題。請看到最後就能獲取你想要的,接下來的是今日的面試題: 1.請說明什麼是Apache Kafka? Apache Kafka是由Apache開發的一種發佈訂閱消息系統,它是一個分散式的、分區的和重覆的日誌服務。 2.請說明什麼是傳統的消息傳遞方法? 傳統的 ...
  • 解壓flume包 到/usr/local/src/目錄下 [root@hadoopha01 pack]# tar -zxvf apache-flume-1.7.0-bin.tar.gz -C /usr/local/src/ 配置flume環境變數 #FLUME_HOME export FLUME_H ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...