本文目錄一覽:
mysql連接超時怎麼處理
MYSQL_OPT_READ_TIMEOUT 是 MySQL c api 客戶端中用來設置讀取超時時間的參數。在 MySQL 的官方文檔中,該參數的描述是這樣的:
MYSQL_OPT_READ_TIMEOUT (argument type: unsigned int *)The timeout in seconds for each attempt to read from the server. There are retries if necessary, so the total effective timeout value is three times the option value. You can set the value so that a lost connection can be detected earlier than the TCP/IPClose_Wait_Timeout value of 10 minutes.
也就是說在需要的時候,實際的超時時間會是設定值的 3 倍。但是實際測試後發現實際的超時時間和設置的超時時間一致。
而具體什麼時候發生三倍超時,在文檔中沒有找到。所以對 MySQL 5.7.20 的源碼進行了一些分析。
使用 GDB 調試代碼找了實際與 mysql server 通信的代碼,如下:
請點擊輸入圖片描述
其中 vio_read() 函數中,使用 recv 和 poll 來讀取報文和做讀取超時。net_should_retry() 函數只有在發生 EINTR 時才會返回 true。從這段代碼來看是符合測試結果的,並沒有對讀取進行三次重試。只有在讀取操作被系統中斷打斷時才會重試,但是這個重試並沒有次數限制。
從上面代碼的分析可以看出,代碼的邏輯和文檔的描述不符。於是在一頓搜索後,找到了一個 MySQL 的 BUG(Bug #31163)。該 BUG 報告了在 MySQL 5.0 中,MySQL c api 讀取的實際超時時間是設置的三倍,與現有文檔描述相符。於是對 MySQL 5.0.96 的代碼又進行分析。
同樣使用 GDB 找到了通信部分的代碼。這次找到了重試三次的代碼,如下:
請點擊輸入圖片描述
這個版本的 MySQL api 的讀寫超時是直接使用的 setsockopt 設置的。第一次循環,在 A 點發生了第一次超時(雖然注釋寫的非阻塞,但是客戶端的連接始終是阻塞模式的)。然後在 B 點將該 socket 設置為阻塞模式,C 點這裡重置 retry 次數。由於設置了 alarm 第二次以後的循環會直接進入 D 點的這個分支,並且判斷循環次數。作為客戶端時net-retry_count 始終是 1,所以重試了兩次,共計進行了 3 次 vioread 後從 E 點退出函數。
由上面的分析可知,MySQL 文檔對於該參數的描述已經過時,現在的 MYSQL_OPT_READ_TIMEOUT 並不會出現三倍超時的問題。而 Bug #31163 中的處理結果也是將文檔中該參數的描述更新為實際讀取超時時間是設定時間的三倍。也許是 MySQL 的維護者們在後續版本更新時忘記更新文檔吧。
如何在Windows的命令行下進行程序編譯和gdb調試
1、概念介紹。
1、Windows下的cmd就是Windows的命令行終端,其中的一些命令和Ubuntu的有些許區別,不過在這個博客的範疇中沒有涉及。
2、Windows的環境變量,大概可以說是如果設置好了在path路徑裏面了,就可以直接在cmd命令行里直接調用程序。
2、配置操作
1、選擇計算機,右鍵,選擇「屬性」
2、「高級系統設置」 – 「環境變量」
3、選擇「環境變量」裏面的「系統變量」 ,選擇path, 編輯
4、添加環境變量。注意:最好不要動原來的東西,在原來的東西的基礎上在前面或後面加上一個分號,然後把Dev C++安裝目錄下的MinGW64/bin文件夾的路徑複製到環境變量裏面去。。(此處是巧借了dev的自帶編譯器,如果各位以其他方法找到了新版的MinGW文件的話,也可以配置成自己喜歡的)注意,路徑中不要出現中文,否則可能出現有趣的問題
(ps:博主這邊用的就不是dev 的MinGW64包了,而是師兄傳下來的 :))
4、一路確定,配置完成。
3、使用操作
在你代碼所在的文件夾,按住shift加右鍵,點擊「在此處打開命令窗口」,進入到cmd終端,接下來就可以愉快地使用g++,gcc編譯器,和gdb調試器了。
4、後期優化
大家還可以給自己配一個用的順手的編輯器,比如sublime,gvim,(甚至是notepad ,hhh)同理把它放在環境變量里,那麼也可以在cmd中直接打開,這時在win下的編程過程就和Ubuntu的非常像了。。
5、備註
1、此處以win7為例,其他版本的應該大同小異。
2、另附片面的gdb調試方法
3、使用編輯器和命令行編譯的方法對於了解程序的運行過程更加有好處,但是從方便性上的確不如IDE,特別是用熟了vs的同學們就應該更能體會得到,所以各有利弊,大家自己選擇最符合自己口味的編程環境就好:)
如何在Windows下編譯或調試MySQL
用vs code 就可以了。
Visual Studio Code
Visual Studio Code(簡稱VS Code)是由微軟開發的,同時支持Windows、Linux和macOS操作系統的開源文本編輯器。它支持調試,內置了Git 版本控制功能,同時也具有開發環境功能,例如代碼補全(類似於IntelliSense)、代碼片段、代碼重構等。該編輯器支持用戶自定義配置,例如改變主題顏色、鍵盤快捷方式、編輯器屬性和其他參數,還支持擴展程序並在編輯器中內置了擴展程序管理的功能。
安裝LLDB
LLDB是LLVM編譯器的一部分,推薦使用Homebrew安裝LLVM工具集,不建議使用系統自帶的LLDB,安裝前必須先創建證書否則無法安裝,步驟如下:
創建完成後,開始安裝LLVM
brew install llvm –with-python@2 –with-lldb
安裝插件
VS Code自帶有debug功能,這裡我推薦使用LLDB Debugger插件。
接下來,為項目配置調試參數。
配置調試參數
使用VS Code打開MySQL源碼目錄,在側邊欄選擇debug欄目,添加配置,program輸入需要調試的程序路徑,這裡選擇你編譯好的mysqld路徑,args輸入程序啟動所需的參數,通常會指定mysqld的配置文件。這樣就配置好了,是不是很簡單。
啟動調試
點擊啟動按鈕,啟動後如果沒有設置斷點會mysqld會正常啟動,如果觸發了斷點會如下圖顯示。
整個調試窗口基本分為六部分,所有的調試操作都在這裡完成:
1: 顯示變量信息
2: 設置重點關注的變量
3: 顯示調用棧信息
4: 設置斷點信息,在代碼行號前也可以設置斷點
5: 代碼顯示區域,上方是調試按鈕,包括 continue/stepover/step in/step out/restart/stop
6: 調試終端輸入輸出區
斷點設置
在代碼行號前點擊即可在該行為設置斷點,也可以根據條件設置斷點。以設置ConditionalBreakpoint為例,當程序啟動後會按照你設置的條件表達式判斷是否觸發斷點。
Conditional Breakpoint這種方式用在目標變量達到某條件時觸發斷點,其餘則跳過繼續執行。比如:設置變量等於目標表名時觸發斷點,其餘表則跳過,相對函數名斷點省去很多手工跳過操作。
遠程調試
假如你想調試遠程Linux服務器上的MySQL上面的方法就不合適了,這時需要遠程調試。lldb和gdb都支持遠程調試,這裡以lldb為例。
需要先在遠程主機上安裝lldb,使用yum安裝,源地址在這裡
remote$ yum install -y llvm-toolset-7
安裝完成後,啟動lldb-server
remote$ /opt/rh/llvm-toolset-7/root/usr/bin/lldb-serverplatform –listen “*:9191” –server
接下來,在VS Code調試界面中新增配置項。
{
“type”: “lldb”,
“request”: “attach”,
“name”: “Remote attach”,
“program”: “~/mysql5626/usr/local/mysql/bin/mysqld”,
“pid”:”target_pid”,
“initCommands”: [
“platform select remote-linux”,
“platform connect connect://remote_host:9191”
],
“sourceMap”: {
“/export/home/pb2/build/sb_0-15908961-1436910670.17/mysql-5.6.26”: “/Users/hongbin/workbench/mysql-server”
}
},
program: 本機也要拷貝一份目標程序,加載
pid: 填寫遠程主機的mysqld進程id
sourceMap: 填寫mysqld編譯的代碼路徑與本機代碼庫路徑的映射,這樣調試時代碼才可以和程序關聯在一起看
注意:記得調試前將代碼切換到與目標程序版本一致的branch
如何用GDB進行調試
1: 對於在應用程序中加入參數進行調試的方法:
直接用 gdb app -p1 -p2 這樣進行調試是不行的。
需要像以下這樣使用:
#gdb app
(gdb) r -p1 -p2
或者在運行run命令前使用set args命令:
(gdb) set args p1 p2
可以用show args 命令來查看
2. 加入斷點:
break linenumber
break funcName
break +offset
break -offset
(在當前行號的前面或後面的offset行停住。)
break filename:linenum
在源文件filename的linenum行處停住。
break filename:function
在源文件filename的function函數的入口處停住。
break … if
…可以是上述的參數,condition表示條件,在條件成立時停住。比如在循環境體中,可以設置 break if i=100,表示當i為100時停住程序。
3. 查看運行時的堆棧:
使用bt命令
4. 打印某個變量的值:
print val
5. 單步: n
繼續運行: c
step
單步跟蹤,如果有函數調用,他會進入該函數。
next
同樣單步跟蹤,如果有函數調用,他不會進入該函數。很像VC等工具中的step over。後面可以加count也可以不加,不加表示一條條地執行,加表示執行後面的count條指令,然後再停住。
set step-mode
set step-mode on
打開step-mode模式,於是,在進行單步跟蹤時,程序不會因為沒有debug信息而不停住。這個參數有很利於查看機器碼。
set step-mod off
關閉step-mode模式。
finish
運行程序,直到當前函數完成返回。並打印函數返回時的堆棧地址和返回值及參數值等信息。
until 或 u
當你厭倦了在一個循環體內單步跟蹤時,這個命令可以運行程序直到退出循環體。
6.在GDB中執行shell命令:
在gdb環境中,你可以執行UNIX的shell的命令,使用gdb的shell命令來完成:
eg. shell make
7. 運行環境
可設定程序的運行路徑。
show paths 查看程序的運行路徑。
set environment varname [=value] 設置環境變量。如:set env USER=hchen
show environment [varname] 查看環境變量。
8.觀察點(WatchPoint)
觀察點一般來觀察某個表達式(變量也是一種表達式)的值是否有變化了,如果有變化,馬上停住程 序。我們有下面的幾種方法來設置觀察點:
watch
為表達式(變量)expr設置一個觀察點。一量表達式值有變化時,馬上停住程序。
rwatch
當表達式(變量)expr被讀時,停住程序。
awatch
當表達式(變量)的值被讀或被寫時,停住程序。
info watchpoints
列出當前所設置了的所有觀察點。
9. 維護breakpoint
clear
清除所有的已定義的停止點。
clear func
清除所有設置在函數上的停止點。
delete [breakpoints] [range…]
刪除指定的斷點,breakpoints為斷點號。如果不指定斷點號,則表示刪除所有的斷點。range 表示斷點號的範圍(如:3-7)。其簡寫命令為d。
比刪除更好的一種方法是disable停止點,disable了的停止點,GDB不會刪除,當你還需要時,enable即可,就好像回收站一樣。
disable [breakpoints] [range…]
disable所指定的停止點,breakpoints為停止點號。如果什麼都不指定,表示disable所有的停止 點。簡寫命令是dis.
enable [breakpoints] [range…]
enable所指定的停止點,breakpoints為停止點號。
10、程序變量
查看文件中某變量的值:
file::variable
function::variable
可以通過這種形式指定你所想查看的變量,是哪個文件中的或是哪個函數中的。例如,查看文件f2.c中的全局變量x的值:
gdb) p ‘f2.c’::x
查看數組的值
有時候,你需要查看一段連續的內存空間的值。比如數組的一段,或是動態分配的數據的大小。你可以使用GDB的「@」操作符,「@」的左邊是第一個內存的地址的值,「@」的右邊則你你想查看內存的長度。例如,你的程序中有這樣的語句:
int *array = (int *) malloc (len * sizeof (int));
於是,在GDB調試過程中,你可以以如下命令顯示出這個動態數組的取值:
p *array@len
如果是靜態數組的話,可以直接用print數組名,就可以顯示數組中所有數據的內容了。
11.輸出格式
一般來說,GDB會根據變量的類型輸出變量的值。但你也可以自定義GDB的輸出的格式。例如,你想輸出一個整數的十六進制,或是二進制來查看這個整型變量的中的位的情況。要做到這樣,你可以使用GDB的數據顯示格式:
x 按十六進制格式顯示變量。
d 按十進制格式顯示變量。
u 按十六進制格式顯示無符號整型。
o 按八進制格式顯示變量。
t 按二進制格式顯示變量。
a 按十六進制格式顯示變量。
c 按字符格式顯示變量。
f 按浮點數格式顯示變量。
(gdb) p i
$21 = 101
(gdb) p/a i
$22 = 0x65
(gdb) p/c i
$23 = 101 ‘e’
(gdb) p/f i
$24 = 1.41531145e-43
(gdb) p/x i
$25 = 0x65
(gdb) p/t i
$26 = 1100101
11.查看內存
使用examine命令(簡寫是x)來查看內存地址中的值。x命令的語法如下所示:
x/
n、f、u是可選的參數。
n 是一個正整數,表示顯示內存的長度,也就是說從當前地址向後顯示幾個地址的內容。
f 表示顯示的格式,參見上面。如果地址所指的是字符串,那麼格式可以是s,如果地十是指令地址,那麼格式可以是i。
u 表示從當前地址往後請求的位元組數,如果不指定的話,GDB默認是4個bytes。u參數可以用下面的字符來代替,b表示單位元組,h表示雙位元組,w表示四位元組,g表示八位元組。當我們指定了位元組長度後,GDB會從指內存定的內存地址開始,讀寫指定位元組,並把其當作一個值取出來。
n/f/u三個參數可以一起使用。例如:
命令:x/3uh 0x54320 表示,從內存地址0x54320讀取內容,h表示以雙位元組為一個單位,3表示三個單位,u表示按十六進制顯示。
12.自動顯示
你可以設置一些自動顯示的變量,當程序停住時,或是在你單步跟蹤時,這些變量會自動顯示。相關的GDB命令是display。
display
display/
display/ expr
expr是一個表達式,fmt表示顯示的格式,addr表示內存地址,當你用display設定好了一個或多個表達式後,只要你的程序被停下來,GDB會自動顯示你所設置的這些表達式的值。
格式i和s同樣被display支持,一個非常有用的命令是:
display/i $pc
undisplay
delete display
刪除自動顯示,dnums意為所設置好了的自動顯式的編號。
disable display
enable display
disable和enalbe不刪除自動顯示的設置,而只是讓其失效和恢復。
info display
查看display設置的自動顯示的信息。GDB會打出一張表格,向你報告當然調試中設置了多少個自動顯示設置,其中包括,設置的編號,表達式,是否enable。
13. 設置顯示選項
set print address
set print address on
打開地址輸出,當程序顯示函數信息時,GDB會顯出函數的參數地址。系統默認為打開的,
show print address
查看當前地址顯示選項是否打開。
set print array
set print array on
打開數組顯示,打開後當數組顯示時,每個元素佔一行,如果不打開的話,每個元素則以逗號分隔。這個選項默認是關閉的。與之相關的兩個命令如下,我就不再多說了。
set print array off
show print array
set print elements
這個選項主要是設置數組的,如果你的數組太大了,那麼就可以指定一個來指定數據顯示的最大長度,當到達這個長度時,GDB就不再往下顯示了。如果設置為0,則表示不限制。
show print elements
查看print elements的選項信息。
set print null-stop
如果打開了這個選項,那麼當顯示字符串時,遇到結束符則停止顯示。這個選項默認為off。
set print pretty on
如果打開printf pretty這個選項,那麼當GDB顯示結構體時會比較漂亮。
14.關於顯示源碼list
gdb調試命令是什麼?
gdb調試命令如下:
1、啟動gdb
$gdb
這樣可以和gdb進行交互了。
2、啟動gdb,並且分屏顯示源代碼
$gdb -tui
這樣,使用了’-tui’選項,啟動可以直接將屏幕分成兩個部分,上面顯示源代碼,比用list方便多了。這時候使用上下方向鍵可以查看源代碼,想要命令行使用上下鍵就用[Ctrl]n和[Ctrl]p。
3、啟動gdb調試指定程序app
$gdb app
這樣就在啟動gdb之後直接載入了app可執行程序,需要注意的是,載入的app程序必須在編譯的時候有gdb調試選項,例如’gcc -g app app.c’,注意,如果修改了程序的源代碼,但是沒有編譯,那麼在gdb中顯示的會是改動後的源代碼,但是運行的是改動前的程序,這樣會導致跟蹤錯亂的。
4、啟動程序之後,再用gdb調試
$gdb program PID
這裡,program是程序的可執行文件名,PID是要調試程序的PID.如果你的程序是一個服務程序,那麼你可以指定這個服務程序運行時的進程ID。gdb會自動attach上去,並調試他。program應該在PATH環境變量中搜索得到。
5、啟動程序之後,再啟動gdb調試
$gdb PID
這裡,程序是一個服務程序,那麼你可以指定這個服務程序運行時的進程ID,PID是要調試程序的PID.這樣gdb就附加到程序上了,但是現在還沒法查看源代碼,用file命令指明可執行文件就可以顯示源代碼了。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/241438.html