国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

線(xiàn)程簡(jiǎn)介和MySQL調試環(huán)境的搭建

發(fā)布時(shí)間:2021-09-14 18:07 來(lái)源:億速云 閱讀:0 作者:chen 欄目: Mysql 歡迎投稿:712375056

本篇內容介紹了“線(xiàn)程簡(jiǎn)介和調試環(huán)境的搭建”的有關(guān)知識,在實(shí)際案例的操作過(guò)程中,不少人都會(huì )遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學(xué)有所成!

一、線(xiàn)程簡(jiǎn)介

我們知道MySQLD是一個(gè)單進(jìn)程多線(xiàn)程的用戶(hù)程序,因此我們有必要了解一下什么線(xiàn)程。實(shí)際上MySQL中的線(xiàn)程都是POSIX線(xiàn)程,比如我們的會(huì )話(huà)線(xiàn)程、DUMP線(xiàn)程、IO線(xiàn)程以及其他一些Innodb線(xiàn)程都是POSIX線(xiàn)程。

進(jìn)程實(shí)際上就是運行中的程序,一個(gè)進(jìn)程中可以包含多個(gè)線(xiàn)程也可以只包含一個(gè)線(xiàn)程。在Linux中線(xiàn)程也叫輕量級進(jìn)程(light-weight process)簡(jiǎn)稱(chēng)為L(cháng)WP,進(jìn)程的第一個(gè)線(xiàn)程通常稱(chēng)為主控線(xiàn)程。進(jìn)程是內存分配的最小單位,線(xiàn)程是CPU調度的最小單位,也就是說(shuō)如果CPU有足夠多核,那么多個(gè)線(xiàn)程可以達到并行處理的效果,內核直接調度線(xiàn)程。下面是我學(xué)習Linux線(xiàn)程的時(shí)候看到的一張我認為比較好理解的圖,我重新畫(huà)了一下放在下面供大家參考(圖29-1,高清原圖包含在文末原圖中):

一個(gè)進(jìn)程內部的所有線(xiàn)程都擁有相同的代碼程序、堆、全局變量、共享庫等,但是每個(gè)線(xiàn)程擁有自己獨立??臻g和寄存器,他們共享進(jìn)程的虛擬內存地址空間。下面我們假定是32位操作系統下的MySQLD進(jìn)程,它的進(jìn)程虛擬內存地址示意圖如下,實(shí)際上這個(gè)圖也是參考《Linux UNIX系統編程手冊》畫(huà)的(圖29-2,高清原圖包含在文末原圖中):

我們發(fā)現線(xiàn)程的堆內存和全局變量是共享的,因此線(xiàn)程之間數據共享很輕松,但是要控制好這些共享內存就需要引入我們的線(xiàn)程同步技術(shù),比如我們常說(shuō)的Mutex。

如果想了解線(xiàn)程到底共享了哪些資源,線(xiàn)程和進(jìn)程到底各有什么優(yōu)勢和劣勢,可執行參考上面我給出的書(shū)籍。

二、PID、LWP ID、Thread TID

如果要進(jìn)行調試就需要了解這三種ID,其中PID和LWP ID是比較重要,因為不管是調試和運維都會(huì )遇到它們,而Thread TID不做多線(xiàn)程開(kāi)發(fā)一般很少用到,下面是我對它們的總結:

  • PID:內核分配,用于識別各個(gè)進(jìn)程的ID。這個(gè)應該是大家最熟悉的。

  • LWP ID:內核分配,用于識別各個(gè)線(xiàn)程的ID,它就像是線(xiàn)程是‘PID’一樣。同一個(gè)進(jìn)程下的所有線(xiàn)程有相同的PID,但是LWP ID卻不一樣,主控線(xiàn)程的LWP ID就是進(jìn)程PID。

  • Thread TID:進(jìn)程內部用于識別各個(gè)線(xiàn)程的內部ID,這個(gè)ID用得不多。

下面我寫(xiě)了一個(gè)簡(jiǎn)單的C測試程序僅僅用于觀(guān)察這些ID,它是通過(guò)主控線(xiàn)程再創(chuàng )建一個(gè)線(xiàn)程,也就是說(shuō)這個(gè)進(jìn)程包含了兩個(gè)線(xiàn)程。它們分別打印自己的PID、LWP ID、Thread TID,然后做一個(gè)循環(huán)自加操作引起高CPU消耗現象便于觀(guān)察。然后我們使用Linux的top -H和ps -eLlf命令分別進(jìn)行觀(guān)察。

  1. 程序輸出

下面是程序的輸出:

# ./gaopengtest 
main thread: pid 13188 tid 2010470144 lwp 13188
new thread:  pid 13188 tid 2010461952 lwp 13189

我們可以看到兩個(gè)線(xiàn)程的PID都是13188,但是主控線(xiàn)程的LWP ID是13188,新建立的一個(gè)線(xiàn)程LWP ID是13189。然后就是Thread TID了,不過(guò)多解釋。

  1. top -H 觀(guān)察如下:

我們可以看到這兩個(gè)線(xiàn)程都是高耗CPU的線(xiàn)程,CPU已經(jīng)處于飽和狀態(tài)。這里我們看到top -H命令的輸出中‘PID’就是LWP ID。這里我們還能看它們的內存信息完全一致,內存信息實(shí)際上是整個(gè)進(jìn)程的內存信息,因為進(jìn)程是內存分配的最小單位嘛。

注意如果這個(gè)時(shí)候查看這個(gè)進(jìn)程占用的%cpu就超過(guò)了100%,接近200%,如下:

  1. ps -eLlf 觀(guān)察如下:

我們可以看到這里包含了PID和LWP ID,不過(guò)多解釋了,大家可以自己去試試。

三、如何將MySQL的線(xiàn)程和LWP ID進(jìn)行對應

在5.7中我們已經(jīng)可以通過(guò)MySQL語(yǔ)句和LWP ID進(jìn)行對應了,這讓性能診斷變得更加便捷。比如我上面的列子如果兩個(gè)高耗CPU的線(xiàn)程是MySQL的線(xiàn)程那么我們就拿到了線(xiàn)程的LWP ID,然后可以通過(guò)語(yǔ)句找到這兩個(gè)線(xiàn)程到底是MySQL的什么線(xiàn)程。語(yǔ)句如下:

mysql> select a.thd_id,b.THREAD_OS_ID,a.user 
,b.TYPE from  sys.processlist 
a,performance_schema.threads  b where b.thread_id=a.thd_id;
+--------+--------------+---------------------------+---------+------------
| thd_id | THREAD_OS_ID | user                      | conn_id | TYPE       
+--------+--------------+---------------------------+---------+------------
|      1 |        16370 | sql/main                  |    NULL | BACKGROUND 
|      2 |        17202 | sql/thread_timer_notifier |    NULL | BACKGROUND 
|      3 |        17207 | innodb/io_ibuf_thread     |    NULL | BACKGROUND 
|      4 |        17208 | innodb/io_log_thread      |    NULL | BACKGROUND 
|      5 |        17209 | innodb/io_read_thread     |    NULL | BACKGROUND 
|      6 |        17210 | innodb/io_read_thread     |    NULL | BACKGROUND 
|      7 |        17211 | innodb/io_read_thread     |    NULL | BACKGROUND 
|      8 |        17212 | innodb/io_read_thread     |    NULL | BACKGROUND 
|      9 |        17213 | innodb/io_read_thread     |    NULL | BACKGROUND 
|     10 |        17214 | innodb/io_read_thread     |    NULL | BACKGROUND 
|     11 |        17215 | innodb/io_read_thread     |    NULL | BACKGROUND 
|     12 |        17216 | innodb/io_read_thread     |    NULL | BACKGROUND 
|     13 |        17217 | innodb/io_write_thread    |    NULL | BACKGROUND 
|     14 |        17218 | innodb/io_write_thread    |    NULL | BACKGROUND 
|     15 |        17219 | innodb/io_write_thread    |    NULL | BACKGROUND 
|     16 |        17220 | innodb/io_write_thread    |    NULL | BACKGROUND 
|     17 |        17221 | innodb/io_write_thread    |    NULL | BACKGROUND 
......

這里的THREAD_OS_ID就是線(xiàn)程的LWP ID。然后我們使用剛才的ps -eLlf命令再看一下,如下:

我們可以發(fā)現他們是可以對應上的,這個(gè)最好自己實(shí)際試試就知道了。

四、調試環(huán)境搭建

調試環(huán)境的搭建我認為不管使用什么方法只要能夠起到調試的作用就可以了。這里介紹一下我的方法。我是在Linux下面直接使用gdb調試的,我覺(jué)得這個(gè)方法搭建非常簡(jiǎn)單并且很奏效,基本上只要會(huì )源碼安裝就能完成調試環(huán)境的搭建。下面來(lái)看看步驟:

1. 第一步下載MySQL源碼包,解壓。

我特意重新下載了官方版的5.7.26源碼。

2. 使用源碼安裝的方法安裝MySQL,注意需要開(kāi)啟debug選項

下面是我使用的選項:

注意最后的-DWITH_DEBUG=1必須開(kāi)啟。

3. make&&make install

編譯和安裝。

4. 準備參數文件和初始化MySQL數據庫,并且確保能成功啟動(dòng)

這一步自己處理,注意權限。我的環(huán)境啟動(dòng)成功了如下:

[root@gp1 support-files]# ./mysql.server start
Starting MySQL....... SUCCESS! 
[root@gp1 support-files]# ./mysql.server stop
Shutting down MySQL.. SUCCESS!

5. 準備gdb命令文件

如下是我準備的命令文件:

[root@gp1 ~]# more debug.file 
break main
run --defaults-file=/root/sf/mysql3312/my.cnf --user=mysql --gdb

第一行是在main函數處打一個(gè)斷點(diǎn)。第二行就是gdb調用MySQLD的時(shí)候,MySQLD加什么參數了,注意run不要寫(xiě)掉了。

6.使用gdb啟動(dòng)MySQL

使用如下命令啟動(dòng)調試環(huán)境:

gdb -x /root/debug.file /root/sf/mysql3312/bin/mysqld

下面就是我啟動(dòng)調試環(huán)境成功的記錄:

# gdb -x /root/debug.file /root/sf/mysql3312/bin/mysqld
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 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 tribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/sf/mysql3312/bin/mysqld...done.
Breakpoint 1 at 0xec7c53: file /root/sf/mysql-5.7.26/sql/main.cc, line 25.
[Thread debugging using libthread_db enabled]
Breakpoint 1, main (argc=5, argv=0x7fffffffe3b8) at /root/sf/mysql-5.7.26/sql/main.cc:25
25        return mysqld_main(argc, argv);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.212.el6.x86_64 libaio-0.3.107-10.el6.x86_64 libgcc-4.4.7-18.el6.x86_64 libstdc++-4.4.7-18.el6.x86_64 nss-softokn-freebl-3.14.3-23.3.el6_8.x86_64
(gdb) c
Continuing.
[New Thread 0x7fffee883700 (LWP 29375)]
[New Thread 0x7fff9a9f3700 (LWP 29376)]
[New Thread 0x7fff99ff2700 (LWP 29377)]
[New Thread 0x7fff995f1700 (LWP 29378)]
[New Thread 0x7fff98bf0700 (LWP 29379)]
[New Thread 0x7fff981ef700 (LWP 29380)]
[New Thread 0x7fff977ee700 (LWP 29381)]
[New Thread 0x7fff96ded700 (LWP 29382)]
[New Thread 0x7fff963ec700 (LWP 29383)]
.....

注意到了這里的LWP ID了嗎,前面我們已經(jīng)討論過(guò)了。這個(gè)時(shí)候MySQL客戶(hù)端程序已經(jīng)可以連接MySQLD了如下:

# /root/sf/mysql3312/bin/mysql -S'/root/sf/mysql3312/mysql3312.sock'
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.26-debug-log Source distribution
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select version() ;
+------------------+
| version()        |
+------------------+
| 5.7.26-debug-log |
+------------------+
1 row in set (0.00 sec)

好了到這里基本的調試環(huán)境就搭建起來(lái)了,我們可以發(fā)現很簡(jiǎn)單。之后我們就可以進(jìn)行斷點(diǎn)調試了。我常用的gdb命令包含:

  • info threads:查看全部線(xiàn)程

  • thread n:指定某個(gè)線(xiàn)程

  • bt:查看某個(gè)線(xiàn)程棧幀

  • b:設置斷點(diǎn)

  • c:繼續執行

  • s:執行一行代碼,如果代碼函數調用,則進(jìn)入函數

  • n:執行一行代碼,函數調用不進(jìn)入

  • p:打印某個(gè)變量值

  • list:打印代碼的文本信息

當然gdb還有很多命令,可自行參考其他資料。

六、使用調試環(huán)境證明問(wèn)題的一個(gè)列子

這里我們就用一個(gè)例子來(lái)看看調試環(huán)境的使用方法。我們前面第15節說(shuō)過(guò)binlog cache是在order commit的flush階段才寫(xiě)入到binary log的,調用的是函數binlog_cache_data::flush。好了我們可以將斷點(diǎn)打到這個(gè)函數如下:

(gdb) b binlog_cache_data::flush
Breakpoint 2 at 0x1846333: file /root/sf/mysql-5.7.26/sql/binlog.cc, line 1674.

然后我們在MySQL客戶(hù)端執行一個(gè)事物如下,并且提交:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into gpdebug values(1);
Query OK, 1 row affected (0.03 sec)
mysql> commit;

commit的時(shí)候已經(jīng)卡主了,斷點(diǎn)觸發(fā)如下:

Breakpoint 2, binlog_cache_data::flush (this=0x7fff3c00df20...)
    at /root/sf/mysql-5.7.26/sql/binlog.cc:1674
1674      DBUG_ENTER("binlog_cache_data::flush");

我們使用bt命令查看棧幀發(fā)現如下:

#0  binlog_cache_data::flush
at /root/sf/mysql-5.7.26/sql/binlog.cc:1674
#1  0x0000000001861b41 in binlog_cache_mngr::flush 
at /root/sf/mysql-5.7.26/sql/binlog.cc:967
#2  0x00000000018574ce in MYSQL_BIN_LOG::flush_thread_caches 
at /root/sf/mysql-5.7.26/sql/binlog.cc:8894
#3  0x0000000001857712 in MYSQL_BIN_LOG::process_flush_stage_queue 
at /root/sf/mysql-5.7.26/sql/binlog.cc:8957
#4  0x0000000001858d19 in MYSQL_BIN_LOG::ordered_commit 
at /root/sf/mysql-5.7.26/sql/binlog.cc:9595
#5  0x00000000018573b4 in MYSQL_BIN_LOG::commit
at /root/sf/mysql-5.7.26/sql/binlog.cc:8851
#6  0x0000000000f58de9 in ha_commit_trans 
at /root/sf/mysql-5.7.26/sql/handler.cc:1799
#7  0x000000000169e02b in trans_commit 
at /root/sf/mysql-5.7.26/sql/transaction.cc:239
......

好了看到這個(gè)棧幀,就能證明我們的說(shuō)法了,如果想深入學(xué)習代碼就可以從這個(gè)棧幀出發(fā)進(jìn)行學(xué)習。但是值得注意的是,這是建立在知道函數接口功能的前提下的,如果我們不知道寫(xiě)入binary log會(huì )調用binlog_cache_data::flush函數那么調試也就不好進(jìn)行了,我就經(jīng)常遇到這樣的困境。因此整個(gè)系列我給出了很多這樣的接口,供有興趣的朋友調試和測試。

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

精品无码国产自产拍在线观看| yw尤物av无码| 国产一区二区三区无码免费 | 蜜芽久久人人超碰爱香蕉| 国产精品无码V在线观看| 欧美疯狂性受XXXXX喷水|