日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
MySQL客戶(hù)端不辭而別,服務(wù)端怎么辦?

今天我們來(lái)介紹另一種場(chǎng)景:MySQL 客戶(hù)端給服務(wù)端發(fā)送一條 SQL 之后,服務(wù)端執(zhí)行 SQL 的過(guò)程中,客戶(hù)端沒(méi)有任何通知,就直接斷開(kāi)了連接。

這種情況下,服務(wù)端會(huì)怎么辦?

本文內(nèi)容基于 MySQL 8.0.32 源碼,涉及存儲(chǔ)引擎為 InnoDB。

正文

1、兩種場(chǎng)景對(duì)比

為了和前一篇文章介紹的場(chǎng)景區(qū)分開(kāi),我們用兩個(gè)虛構(gòu)小故事把兩種場(chǎng)景放在一起作個(gè)對(duì)比。

場(chǎng)景一:MySQL 客戶(hù)端 Ctrl + C,服務(wù)端會(huì)發(fā)生什么?

張三(MySQL 客戶(hù)端)和李四(服務(wù)端)是好朋友,它送給了李四一個(gè)禮物(發(fā)送了一條 DML/DDL SQL)。

有一天,張三和李四鬧別扭,它后悔送禮物給李四了,于是它對(duì)李四說(shuō):把我送你的禮物還給我(??Ctrl + C 要求服務(wù)端中斷 SQL 執(zhí)行??)。

李四要先把張三送給它的禮物找出來(lái),才能還給張三。

如果禮物還在(事務(wù)還沒(méi)有提交),李四就能把禮物還給張三(中斷執(zhí)行,回滾事務(wù));如果禮物不在了(事務(wù)已經(jīng)提交了),也就沒(méi)法還了。

場(chǎng)景二:MySQL 客戶(hù)端不辭而別,服務(wù)端怎么辦?

張三(MySQL 客戶(hù)端)和李四(服務(wù)端)是好朋友,它送給了李四一個(gè)禮物(發(fā)送了一條 DML/DDL SQL)。

有一天,李四因?yàn)橐患虑榘褟埲敲恕?/p>

張三心里很不爽,它要跟李四絕交(直接斷開(kāi)了連接),但對(duì)它而言,送出去的禮物就是潑出去的水,它不想收回。

李四的性格大大咧咧,它不知道自己把張三惹毛了,還在美滋滋的欣賞張三送給它的禮物(執(zhí)行 SQL)。

等它回過(guò)頭來(lái)想找張三的時(shí)候,發(fā)現(xiàn)找不著了,它才回想起來(lái),可能自己把張三惹毛了,朋友沒(méi)得做了。

此時(shí),李四要怎么對(duì)待張三送給它的禮物呢?

接下來(lái),我們跳出虛構(gòu),回歸現(xiàn)實(shí),來(lái)捋一下場(chǎng)景二的流程。

這種場(chǎng)景只會(huì)出現(xiàn)在通過(guò)程序連接 MySQL 服務(wù)端,程序沒(méi)有關(guān)閉數(shù)據(jù)庫(kù)連接就執(zhí)行結(jié)束或者崩潰了

2、客戶(hù)端不辭而別

MySQL 客戶(hù)端發(fā)送一條 DML/DDL SQL 給服務(wù)端,服務(wù)端收到之后,就開(kāi)始吭哧吭哧地執(zhí)行。

SQL 執(zhí)行完成之前,客戶(hù)端再?zèng)]有給服務(wù)端發(fā)送任何消息,就直接斷開(kāi)連接了。

SQL 執(zhí)行過(guò)程中,服務(wù)端并不能感知到連接已經(jīng)斷開(kāi)了,它還會(huì)一直賣(mài)力地執(zhí)行 SQL。

SQL 執(zhí)行完成之后,問(wèn)題來(lái)了。

3、服務(wù)端怎么辦?

(1)先提交事務(wù)再回滾

如果服務(wù)端執(zhí)行的是 DDL 語(yǔ)句,一條 SQL 執(zhí)行完成之后,會(huì)自動(dòng)提交事務(wù)。

如果服務(wù)端執(zhí)行的是 DML? 語(yǔ)句,并且系統(tǒng)變量 auto_commit = on,一條 SQL 執(zhí)行完成之后,也會(huì)自動(dòng)提交事務(wù)。

因?yàn)榉?wù)端不知道客戶(hù)端已經(jīng)斷開(kāi)連接了,事務(wù)提交之后,它會(huì)把 SQL 執(zhí)行結(jié)果發(fā)送給客戶(hù)端。

把結(jié)果發(fā)送給客戶(hù)端,執(zhí)行的是 send() 系統(tǒng)調(diào)用,send() 有兩種行為:

行為一,如果 send() 把 SQL 執(zhí)行結(jié)果寫(xiě)入 socket 緩沖區(qū),會(huì)返回寫(xiě)入成功,此時(shí),服務(wù)端還不會(huì)感知到客戶(hù)端已經(jīng)斷開(kāi)連接。

send() 執(zhí)行成功之后,服務(wù)端認(rèn)為這條 SQL 就告一段落了,會(huì)等待客戶(hù)端發(fā)送下一條命令。

由于客戶(hù)端已經(jīng)斷開(kāi)連接,從當(dāng)前連接讀取下一條命令時(shí)會(huì)出錯(cuò)。

此時(shí),服務(wù)端會(huì)感知到客戶(hù)端已經(jīng)斷開(kāi)連接了。

行為二,如果 send() 直接把 SQL 執(zhí)行結(jié)果發(fā)送給客戶(hù)端,服務(wù)端就能馬上感知到客戶(hù)端已經(jīng)斷開(kāi)連接了。

不管 send() 發(fā)生哪種行為,服務(wù)端都會(huì)感知到客戶(hù)端已經(jīng)斷開(kāi)連接了,無(wú)非早一點(diǎn)晚一點(diǎn)而已。

感知到連接斷開(kāi)之后,服務(wù)端會(huì)回滾事務(wù)。

但是,由于執(zhí)行 send() 之前,服務(wù)端已經(jīng)把事務(wù)提交了,這里回滾事務(wù)并不會(huì)生效。

那么,最終結(jié)果就是:服務(wù)端對(duì)于數(shù)據(jù)的修改會(huì)被持久化,永久生效。

(2)回滾事務(wù)

如果服務(wù)端執(zhí)行的是 DML 語(yǔ)句,并且用 begin 或 start transaction 顯式開(kāi)啟了事務(wù),一條 SQL 執(zhí)行完成之后,不會(huì)自動(dòng)提交事務(wù),而是會(huì)等待客戶(hù)端發(fā)送下一條命令。

讀取下一條命令之前,服務(wù)端會(huì)執(zhí)行 send() 系統(tǒng)調(diào)用,把當(dāng)前 SQL 的執(zhí)行結(jié)果發(fā)送給客戶(hù)端。

send() 有兩種行為:

?行為一,如果 send() 把 SQL 執(zhí)行結(jié)果寫(xiě)入 socket 緩沖區(qū),會(huì)返回寫(xiě)入成功,此時(shí),服務(wù)端還不會(huì)感知到客戶(hù)端已經(jīng)斷開(kāi)連接。

send() 執(zhí)行成功之后,服務(wù)端認(rèn)為這條 SQL 就告一段落了,會(huì)等待客戶(hù)端發(fā)送下一條命令。

由于客戶(hù)端已經(jīng)斷開(kāi)連接,從當(dāng)前連接讀取下一條命令時(shí)會(huì)出錯(cuò)。

此時(shí),服務(wù)端會(huì)感知到客戶(hù)端已經(jīng)斷開(kāi)連接了。

行為二,如果 send() 直接把 SQL 執(zhí)行結(jié)果發(fā)送給客戶(hù)端,服務(wù)端就能馬上感知到客戶(hù)端已經(jīng)斷開(kāi)連接了。

不管 send() 發(fā)生哪種行為,服務(wù)端都會(huì)感知到客戶(hù)端已經(jīng)斷開(kāi)連接了,無(wú)非早一點(diǎn)晚一點(diǎn)而已。

感知到連接斷開(kāi)之后,服務(wù)端會(huì)回滾事務(wù)?,由于執(zhí)行 send() 之前,并沒(méi)有提交過(guò)事務(wù),這里回滾事務(wù)會(huì)生效。

那么,最終結(jié)果就是:服務(wù)端對(duì)于數(shù)據(jù)的修改會(huì)被回滾,相當(dāng)于沒(méi)有執(zhí)行過(guò) DML 操作。

4、總結(jié)

前面展開(kāi)介紹了 MySQL 客戶(hù)端不辭而別之后,服務(wù)端進(jìn)行的一系列操作,總結(jié)起來(lái)就 3 條:

第 1 條:如果服務(wù)端執(zhí)行的是 DDL 語(yǔ)句,DDL 會(huì)執(zhí)行成功。

第 2 條:如果服務(wù)端執(zhí)行的是 DML? 語(yǔ)句,并且系統(tǒng)變量 auto_commit = on,DML 也會(huì)執(zhí)行成功。

第 3 條:如果服務(wù)端執(zhí)行的是 DML? 語(yǔ)句,并且用 begin、start transaction 顯式開(kāi)啟了事務(wù)或者系統(tǒng)變量 auto_commit = off,事務(wù)會(huì)被回滾,DML 相當(dāng)于沒(méi)有執(zhí)行。

5、遺留問(wèn)題

前面介紹到 send() 有兩種行為:

  • 先把 SQL 執(zhí)行結(jié)果寫(xiě)入 socket 緩沖區(qū),緩沖區(qū)滿(mǎn)再發(fā)送給客戶(hù)端。
  • 直接把 SQL 執(zhí)行結(jié)果發(fā)送給客戶(hù)端。

這兩種行為由操作系統(tǒng)內(nèi)核決定,目前對(duì)于這個(gè)機(jī)制還沒(méi)有完全研究清楚,留待后續(xù)。

本文轉(zhuǎn)載自微信公眾號(hào)「一樹(shù)一溪」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系一樹(shù)一溪公眾號(hào)。


名稱(chēng)欄目:MySQL客戶(hù)端不辭而別,服務(wù)端怎么辦?
新聞來(lái)源:http://www.5511xx.com/article/dhgpico.html