<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          新手如何用 VSCode 調(diào)試 MySQL

          共 4174字,需瀏覽 9分鐘

           ·

          2022-05-27 19:19

          前幾天看到姜老師的舊文用 VSCode 編譯和調(diào)試 MySQL,每個(gè) DBA 都應(yīng) get 的小技能[1], 文末留了一個(gè)思考題,如何修改源碼,自定義版本,使得 select version() 輸出自定義內(nèi)容

          調(diào)試過(guò)程參考macOS VSCode 編譯調(diào)試 MySQL 5.7[2]

          內(nèi)部 Item 對(duì)象參考從SQL語(yǔ)句到MySQL內(nèi)部對(duì)象[3]

          源碼面前沒(méi)有秘密,建義對(duì) DB 感興趣的嘗試 debug 調(diào)試。本文環(huán)境為 mac + vscode + lldb

          依賴(lài)及插件

          vscode 插件:

          • C/C++
          • C/C++ Clang Command Adapter
          • CodeLLDB
          • CMake Tools

          mysql 源碼:

          • mysql-boost-5.7.35.tar.gz

          補(bǔ)?。?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">MySQL <= 8.0.21 需要對(duì) cmake/mysql_version.cmake 文件打補(bǔ)丁 (沒(méi)有嚴(yán)格測(cè)試所有版本)

          tar?-zxf?mysql-boost-5.7.35.tar.gz
          cd?mysql-5.7.35
          mv?VERSION?MYSQL_VERSION
          sed?-i?''?'s|${CMAKE_SOURCE_DIR}/VERSION|${CMAKE_SOURCE_DIR}/MYSQL_VERSION|g'?cmake/mysql_version.cmake

          創(chuàng)建 cmake-build-debug 目錄,后續(xù) mysql 編譯結(jié)果,以及啟動(dòng)后生成的文件都在這里

          mkdir?-p?cmake-build-debug/{data,etc}

          配置 CMake 與編譯

          在 mysql 工程目錄下面創(chuàng)建 .vscode/settings.json 文件

          {
          ????"cmake.buildBeforeRun":?true,
          ????"cmake.buildDirectory":?"${workspaceFolder}/cmake-build-debug/build",
          ????"cmake.configureSettings":?{
          ????????"WITH_DEBUG":?"1",
          ????????"CMAKE_INSTALL_PREFIX":?"${workspaceFolder}/cmake-build-debug",
          ????????"MYSQL_DATADIR":?"${workspaceFolder}/cmake-build-debug/data",
          ????????"SYSCONFDIR":?"${workspaceFolder}/cmake-build-debug/etc",
          ????????"MYSQL_TCP_PORT":?"3307",
          ????????"MYSQL_UNIX_ADDR":?"${workspaceFolder}/cmake-build-debug/data/mysql-debug.sock",
          ????????"WITH_BOOST":?"${workspaceFolder}/boost",
          ????????"DOWNLOAD_BOOST":?"0",
          ????????"DOWNLOAD_BOOST_TIMEOUT":?"600"
          ????}
          }

          內(nèi)容沒(méi)啥好說(shuō)的,都是指定目錄及 boost 配置,其中 WITH_DEBUG 打開(kāi) debug 模式,會(huì)在 /tmp/debug.trace 生成 debug 信息

          View -> Command Palette -> CMake: Configure 執(zhí)行后生成 cmake 配置

          View -> Command Palette -> CMake: Build 編譯生成最終 mysql 相關(guān)命令

          發(fā)現(xiàn)老版本編譯很麻煩,各種報(bào)錯(cuò),mysql 5.7 代碼量遠(yuǎn)超過(guò) 5.5, 只能硬著頭皮看 5.7

          初始化數(shù)據(jù)庫(kù)

          首先初始化 my.cnf 配置,簡(jiǎn)單的就可以,共它均默認(rèn)

          cd?cmake-build-debug
          cat?>?etc/my.cnf?<[mysqld]
          port=3307
          socket=mysql.sock
          innodb_file_per_table=1
          log_bin?=?on
          server-id?=?10086
          binlog_format?=?ROW
          EOF

          初始化數(shù)據(jù)文件,非安全模式,調(diào)試用

          ./build/sql/mysqld?--defaults-file=etc/my.cnf?--initialize-insecure
          tree?-L?1?data
          data
          ├──?auto.cnf
          ├──?ca-key.pem
          ├──?ca.pem
          ├──?client-cert.pem
          ├──?client-key.pem
          ├──?ib_buffer_pool
          ├──?ib_logfile0
          ├──?ib_logfile1
          ├──?ibdata1
          ├──?mysql
          ├──?on.000001
          ├──?on.index
          ├──?performance_schema
          ├──?private_key.pem
          ├──?public_key.pem
          ├──?server-cert.pem
          ├──?server-key.pem
          └──?sys

          運(yùn)行 MySQL

          由于用 vscode 接管 mysql, 所以需要配置 .vscode/launch.json

          {
          ????//?使用 IntelliSense 了解相關(guān)屬性。?
          ????//?懸停以查看現(xiàn)有屬性的描述。
          ????//?欲了解更多信息,請(qǐng)?jiān)L問(wèn):?https://go.microsoft.com/fwlink/?linkid=830387
          ????"version":?"0.2.0",
          ????"configurations":?[
          ????????{
          ????????????"type":?"lldb",
          ????????????"request":?"launch",
          ????????????"name":?"Debug?mysqld",
          ????????????"program":?"${workspaceFolder}/cmake-build-debug/build/sql/mysqld",
          ????????????"args":?[
          ????????????????"--defaults-file=${workspaceFolder}/cmake-build-debug/etc/my.cnf",?"--debug"
          ????????????],
          ????????????"cwd":?"${workspaceFolder}"
          ????????},
          ????????{
          ????????????"type":?"lldb",
          ????????????"request":?"launch",
          ????????????"name":?"Debug?mysql",
          ????????????"program":?"${workspaceFolder}/cmake-build-debug/build/client/mysql",
          ????????????"args":?[
          ????????????????"-uroot",
          ????????????????"-P3307",
          ????????????????"-h127.0.0.1"
          ????????????],
          ????????????"cwd":?"${workspaceFolder}"
          ????????}
          ????]
          }

          然后點(diǎn)擊 run and debug mysqld

          mysql 啟動(dòng),看到輸出日志無(wú)異常,此時(shí)可以用 mysql-client 連接

          mysql?-uroot?-S?./data/mysql.sock

          調(diào)試

          首先在 sql_parser.cc:5435 處打斷點(diǎn)

          void?mysql_parse(THD?*thd,?Parser_state?*parser_state)

          mysql_parse 是 sql 處理的入口,至于 tcp connection 連接先可以忽略

          mysql>?select?version();

          執(zhí)行上述 sql 自動(dòng)跳轉(zhuǎn)到斷點(diǎn)處,Step Into, Step Over, Step Out 這些調(diào)試熟悉下即可

          接下來(lái)分別調(diào)用主要函數(shù):mysql_execute_command, execute_sqlcom_select, handle_query, select->join->exec(), Query_result_send::send_data, Item::send, Item_string:val_str, Protocol_text::store, net_send_ok

          修改源碼

          啟動(dòng) mysql 時(shí) init_common_variables 會(huì)初始化一堆變量,其中會(huì)調(diào)用 set_server_version 生成版本信息,修改這個(gè)就可以

          static?void?set_server_version(void)
          {
          ??char?*end=?strxmov(server_version,?MYSQL_SERVER_VERSION,
          ?????????????????????MYSQL_SERVER_SUFFIX_STR,?NullS);
          ......
          #ifndef?NDEBUG
          ??if?(!strstr(MYSQL_SERVER_SUFFIX_STR,?"-debug"))
          ????end=?my_stpcpy(end,?"-dongzerun");
          #endif
          ??if?(opt_general_log?||?opt_slow_log?||?opt_bin_log)
          ????end=?my_stpcpy(end,?"-log");??????????//?This?may?slow?down?system
          ......
          }

          看好條件編譯的是哪塊,修改即可,重新 CMake: Build 編譯再運(yùn)行

          mysql>?select?version();
          +----------------------+
          |?version()????????????|
          +----------------------+
          |?5.7.35-dongzerun-log?|
          +----------------------+
          1?row?in?set?(0.00?sec)

          Item Class

          這里不做過(guò)深分析,簡(jiǎn)單講

          • select version(), select now() 這些簡(jiǎn)單 sql 在 server 層就能得到結(jié)果,無(wú)需進(jìn)入引擎層
          • version(), now() 這些函數(shù)在 yacc&lex 詞法解析時(shí)就會(huì)解析成對(duì)應(yīng)的 Item 類(lèi)
          • 最后 mysql 渲染結(jié)果時(shí),就是由 Item::itemize 寫(xiě)到 result 中
          function_call_generic:
          ??????????IDENT_sys?'('?opt_udf_expr_list?')'
          ??????????{
          ????????????$$=?NEW_PTN?PTI_function_call_generic_ident_sys(@1,?$1,?$3);
          ??????????}
          ????????|?ident?'.'?ident?'('?opt_expr_list?')'
          ??????????{
          ????????????$$=?NEW_PTN?PTI_function_call_generic_2d(@$,?$1,?$3,?$5);
          ??????????}
          ????????;

          sql_yacc.cc 函數(shù) PTI_function_call_generic_ident_sys 解析 sql, 識(shí)別出 version() 是一個(gè)函數(shù)調(diào)用

          ??virtual?bool?itemize(Parse_context?*pc,?Item?**res)
          ??
          {
          ????if?(super::itemize(pc,?res))
          ??????return?true;
          ......

          ????/*
          ??????Implementation?note:
          ??????names?are?resolved?with?the?following?order:
          ??????-?MySQL?native?functions,
          ??????-?User?Defined?Functions,
          ??????-?Stored?Functions?(assuming?the?current??database)

          ??????This?will?be?revised?with?WL#2128?(SQL?PATH)
          ????*/

          ????Create_func?*builder=?find_native_function_builder(thd,?ident);
          ????if?(builder)
          ??????*res=?builder->create_func(thd,?ident,?opt_udf_expr_list);
          ......
          ????return?*res?==?NULL?||?(*res)->itemize(pc,?res);
          ??}

          find_native_function_builder 查找 hash 表,找到對(duì)應(yīng) version 函數(shù)注冊(cè)的單例工廠函數(shù)

          static?Native_func_registry?func_array[]?=
          {
          ??{?{?C_STRING_WITH_LEN("ABS")?},?BUILDER(Create_func_abs)},
          ??{?{?C_STRING_WITH_LEN("ACOS")?},?BUILDER(Create_func_acos)},
          ......
          ??{?{?C_STRING_WITH_LEN("VERSION")?},?BUILDER(Create_func_version)},
          ......
          ??{?{0,?0},?NULL}
          };

          mysql 啟動(dòng)時(shí)調(diào)用 item_create_init 將這些函數(shù) builder 注冊(cè)到 hash 表 native_functions_hash

          Create_func_version?Create_func_version::s_singleton;

          Item*
          Create_func_version::create(THD?*thd)
          {
          ??return?new?(thd->mem_root)?Item_func_version(POS());
          }
          class?Item_func_version?:?public?Item_static_string_func
          {
          ??typedef?Item_static_string_func?super;
          public:
          ??explicit?Item_func_version(const?POS?&pos)
          ????:?Item_static_string_func(pos,?NAME_STRING("version()"),
          ??????????????????????????????server_version,
          ??????????????????????????????strlen(server_version),
          ??????????????????????????????system_charset_info,
          ??????????????????????????????DERIVATION_SYSCONST)

          ??
          {}

          ??virtual?bool?itemize(Parse_context?*pc,?Item?**res);
          };

          可以看到 Item_func_version 函數(shù)創(chuàng)建時(shí)傳參即為 mysql server_version 版本信息

          小結(jié)

          MySQL 代碼太龐大,5.1 大約 100w 行,5.5 130w 行,5.7 以后 330w 行,只能挑重點(diǎn)讀源碼。最近很多群里的人在背八股,沒(méi)必要,有那時(shí)間學(xué)著調(diào)試下源碼,讀讀多好

          分享知識(shí),長(zhǎng)期輸出價(jià)值,這是我做公眾號(hào)的目標(biāo)。同時(shí)寫(xiě)文章不容易,如果對(duì)大家有所幫助和啟發(fā),請(qǐng)幫忙點(diǎn)擊在看,點(diǎn)贊,分享 三連

          參考資料

          [1]

          用 VSCode 編譯和調(diào)試 MySQL,每個(gè) DBA 都應(yīng) get 的小技能: https://www.modb.pro/db/112992,

          [2]

          macOS VSCode 編譯調(diào)試 MySQL 5.7: https://shockerli.net/post/mysql-source-macos-vscode-debug-5-7/,

          [3]

          從SQL語(yǔ)句到MySQL內(nèi)部對(duì)象: https://www.orczhou.com/index.php/2012/11/mysql-innodb-source-code-optimization-1/#21_Item,



          推薦閱讀


          福利

          我為大家整理了一份從入門(mén)到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門(mén)看什么,進(jìn)階看什么。關(guān)注公眾號(hào) 「polarisxu」,回復(fù)?ebook?獲??;還可以回復(fù)「進(jìn)群」,和數(shù)萬(wàn) Gopher 交流學(xué)習(xí)。


          瀏覽 146
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青伊人久久 | 在线看特及黄色片 | 黄a免费视频在线观看 | 家庭乱伦影视 | 亚洲欧美高清在线观看 |