<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>

          面試官:為什么數(shù)據(jù)庫(kù)連接很消耗資源?我竟然答不上來(lái)。。一下懵了!

          共 2904字,需瀏覽 6分鐘

           ·

          2022-05-31 17:35

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

          背景

          開(kāi)發(fā)應(yīng)用程序久了,總想刨根問(wèn)底,尤其對(duì)一些有公共答案的問(wèn)題。大家都能解釋,但是追根究底,都解釋不清。凡是都有為什么,而且用數(shù)字說(shuō)明問(wèn)題是最直觀的。

          本文主要想探究一下連接數(shù)據(jù)庫(kù)的細(xì)節(jié),尤其是在 Web 應(yīng)用中要使用數(shù)據(jù)庫(kù)來(lái)連接池,以免每次發(fā)送一次請(qǐng)求就重新建立一次連接。

          對(duì)于這個(gè)問(wèn)題,答案都是一致的,建立數(shù)據(jù)庫(kù)連接很耗時(shí),但是這個(gè)耗時(shí)是都多少呢,又是分別在哪些方面產(chǎn)生的耗時(shí)呢?

          分析

          本文以連接 MySQL 數(shù)據(jù)庫(kù)為例,因?yàn)?MySQL 數(shù)據(jù)庫(kù)是開(kāi)源的,其通信協(xié)議是公開(kāi)的,所以我們能夠詳細(xì)分析建立連接的整個(gè)過(guò)程。

          在本文中,消耗資源的分析主要集中在網(wǎng)絡(luò)上,當(dāng)然,資源也包括內(nèi)存、CPU 等計(jì)算資源,使用的編程語(yǔ)言是 Java,但是不排除編程語(yǔ)言也會(huì)有一定的影響。

          首先先看一下連接數(shù)據(jù)庫(kù)的 Java 代碼,如下:

          Class.forName("com.mysql.jdbc.Driver");

          String?name?=?"shine_user";
          String?password?=?"123";
          String?url?=?"jdbc:mysql://172.16.100.131:3306/clever_mg_test";
          Connection?conn?=?DriverManager.getConnection(url,?name,?password);
          //?之后程序終止,連接被強(qiáng)制關(guān)閉

          然后通過(guò)「Wireshark」分析整個(gè)連接的建立過(guò)程,如下:

          *Wireshark 抓包*

          在上圖中顯示的連接過(guò)程中,可以看出 MySQL 的通信協(xié)議是基于 TCP 傳輸協(xié)議的,而且該協(xié)議是二進(jìn)制協(xié)議,不是類似于 HTTP 的文本協(xié)議。最新 MySQL?面試題整理好了,大家可以在Java面試庫(kù)小程序在線刷題。

          其中建立連接的過(guò)程具體如下:

          • 第 1 步:建立 TCP 連接,通過(guò)三次握手實(shí)現(xiàn)。
          • 第 2 步:服務(wù)器發(fā)送給客戶端「握手信息」,客戶端響應(yīng)該握手消息。
          • 第 3 步:客戶端「發(fā)送認(rèn)證包」,用于用戶驗(yàn)證,驗(yàn)證成功后,服務(wù)器返回 OK 響應(yīng),之后開(kāi)始執(zhí)行命令。

          用戶驗(yàn)證成功之后,會(huì)進(jìn)行一些連接變量的設(shè)置,比如字符集、是否自動(dòng)提交事務(wù)等,其間會(huì)有多次數(shù)據(jù)的交互。完成了這些步驟后,才會(huì)執(zhí)行真正的數(shù)據(jù)查詢和更新等操作。

          在本文的測(cè)試中,只用了 5 行代碼來(lái)建立連接,但是并沒(méi)有通過(guò)該連接去執(zhí)行任何操作,所以在程序執(zhí)行完畢之后,連接不是通過(guò) Connection.close() 關(guān)閉的,而是由于程序執(zhí)行完畢,導(dǎo)致進(jìn)程終止,造成與數(shù)據(jù)庫(kù)的連接異常關(guān)閉,所以最后會(huì)出現(xiàn) TCP 的 RST 報(bào)文。

          在這個(gè)最簡(jiǎn)單的代碼中,沒(méi)有設(shè)置任何額外的連接屬性,所以在設(shè)置屬性上占用的時(shí)間可以認(rèn)為是最少的(其實(shí),雖然我們沒(méi)有設(shè)置任何屬性,但是驅(qū)動(dòng)仍然設(shè)置了字符集、事務(wù)自動(dòng)提交等,這取決于具體的驅(qū)動(dòng)實(shí)現(xiàn)),所以整個(gè)連接所使用的時(shí)間可以認(rèn)為是最少的。

          但從統(tǒng)計(jì)信息中可以看出,在不包括最后 TCP 的 RST 報(bào)文時(shí)(因?yàn)樵搱?bào)文不需要服務(wù)器返回任何響應(yīng)),但是其中仍需在客戶端和服務(wù)器之間進(jìn)行往返「7」次,「也就是說(shuō)完成一次連接,可以認(rèn)為,數(shù)據(jù)在客戶端和服務(wù)器之間需要至少往返 7 次」。

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

          從時(shí)間上來(lái)看,從開(kāi)始 TCP 的三次握手,到最終連接強(qiáng)制斷開(kāi)為止(不包括最后的 RST 報(bào)文),總共花費(fèi)了:

          10.416042?-?10.190799?=?0.225243s?=?225.243ms

          這意味著,建立一次數(shù)據(jù)庫(kù)連接需要 225ms,而這還是還可以認(rèn)為是最少的,當(dāng)然「花費(fèi)的時(shí)間可能受到網(wǎng)絡(luò)狀況、數(shù)據(jù)庫(kù)服務(wù)器性能以及應(yīng)用代碼是否高效的影響」,但是這里只是一個(gè)最簡(jiǎn)單的例子,已經(jīng)足夠說(shuō)明問(wèn)題了!

          由于上面是程序異常終止了,但是在正常的應(yīng)用程序中,連接的關(guān)閉一般都是通過(guò) Connection.close() 完成的。最新 MySQL 面試題整理好了,大家可以在Java面試庫(kù)小程序在線刷題。

          代碼如下:

          Class.forName("com.mysql.jdbc.Driver");

          String?name?=?"shine_user";
          String?password?=?"123";
          String?url?=?"jdbc:mysql://172.16.100.131:3306/clever_mg_test";
          Connection?conn?=?DriverManager.getConnection(url,?name,?password);
          conn.close();
          *網(wǎng)絡(luò)抓包*

          這樣的話,情況發(fā)生了變化,主要體現(xiàn)在與數(shù)據(jù)庫(kù)連接的斷開(kāi),如上圖:

          • 第 1 步:此時(shí)處于 MySQL 通信協(xié)議階段,客戶端發(fā)送關(guān)閉連接請(qǐng)求,而且不用等待服務(wù)端的響應(yīng)。
          • 第 2 步:TCP 斷開(kāi)連接,4 次揮手完成連接斷開(kāi)。

          這里是完整地完成了從數(shù)據(jù)庫(kù)連接的建立到關(guān)閉,整個(gè)過(guò)程花費(fèi)了:

          747.284311?-?747.100954?=?0.183357s?=?183.357ms

          這里可能也有網(wǎng)絡(luò)狀況的影響,比上述的 225ms 少了,但是也幾乎達(dá)到了 200ms 的級(jí)別。

          那么問(wèn)題來(lái)了,想象一下這個(gè)場(chǎng)景,對(duì)于一個(gè)日活 2 萬(wàn)的網(wǎng)站來(lái)說(shuō),假設(shè)每個(gè)用戶只會(huì)發(fā)送 5 個(gè)請(qǐng)求,那么一天就是 10 萬(wàn)個(gè)請(qǐng)求。

          對(duì)于建立數(shù)據(jù)庫(kù)連接,我們保守一點(diǎn)計(jì)算為 150ms 好了,那么一天當(dāng)中花費(fèi)在建立數(shù)據(jù)庫(kù)連接的時(shí)間有(還不包括執(zhí)行查詢和更新操作):

          100000?*?150ms?=?15000000ms?=?15000s?=?250min?=?4.17h

          也就說(shuō)每天花費(fèi)在建立數(shù)據(jù)庫(kù)連接上的時(shí)間已經(jīng)達(dá)到「4 個(gè)小時(shí)」,所以說(shuō)數(shù)據(jù)庫(kù)連接池是必須的嘛。

          而且當(dāng)日活增加時(shí),單單使用數(shù)據(jù)庫(kù)連接池也不能完全保證你的服務(wù)能夠正常運(yùn)行,還需要考慮其他的解決方案。

          例如:

          • 緩存
          • SQL 的預(yù)編譯
          • 負(fù)載均衡
          • ……

          總結(jié)

          當(dāng)然這不是本文的主要內(nèi)容,本文想要闡述的核心思想只有一個(gè),數(shù)據(jù)庫(kù)連接真的很耗時(shí),所以不要頻繁的建立連接。

          版權(quán)聲明:本文為CSDN博主「lmy86263」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/lmy86263/article/details/76165714








          Spring Boot 定時(shí)任務(wù)開(kāi)啟后,怎么自動(dòng)停止?
          工作 3 年的同事不知道如何回滾代碼
          23 種設(shè)計(jì)模式實(shí)戰(zhàn)(很全)
          Spring Boot 保護(hù)敏感配置的 4 種方法!
          再見(jiàn)單身狗!Java 創(chuàng)建對(duì)象的 6 種方式
          阿里為什么推薦使用 LongAdder?
          新來(lái)一個(gè)技術(shù)總監(jiān):禁止戴耳機(jī)寫(xiě)代碼。。
          重磅!Spring Boot 2.7 正式發(fā)布
          Java 18?正式發(fā)布,finalize 被棄用。
          Spring Boot Admin 橫空出世!
          Spring Boot 學(xué)習(xí)筆記,這個(gè)太全了!



          關(guān)注Java技術(shù)棧看更多干貨



          獲取 Spring Boot 實(shí)戰(zhàn)筆記!
          瀏覽 31
          點(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片免费看 |