成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MySQL 客戶端不辭而別,服務端怎么辦?

數據庫 MySQL
MySQL 客戶端給服務端發送一條 SQL 之后,服務端執行 SQL 的過程中,客戶端沒有任何通知,就直接斷開了連接。

今天我們來介紹另一種場景:MySQL 客戶端給服務端發送一條 SQL 之后,服務端執行 SQL 的過程中,客戶端沒有任何通知,就直接斷開了連接。

這種情況下,服務端會怎么辦?

本文內容基于 MySQL 8.0.32 源碼,涉及存儲引擎為 InnoDB。

正文

1、兩種場景對比

為了和前一篇文章介紹的場景區分開,我們用兩個虛構小故事把兩種場景放在一起作個對比。

場景一:MySQL 客戶端 Ctrl + C,服務端會發生什么?

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

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

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

如果禮物還在(事務還沒有提交),李四就能把禮物還給張三(中斷執行,回滾事務);如果禮物不在了(事務已經提交了),也就沒法還了。

場景二:MySQL 客戶端不辭而別,服務端怎么辦?

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

有一天,李四因為一件事情把張三惹毛了。

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

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

等它回過頭來想找張三的時候,發現找不著了,它才回想起來,可能自己把張三惹毛了,朋友沒得做了。

此時,李四要怎么對待張三送給它的禮物呢?

接下來,我們跳出虛構,回歸現實,來捋一下場景二的流程。

這種場景只會出現在通過程序連接 MySQL 服務端,程序沒有關閉數據庫連接就執行結束或者崩潰了

2、客戶端不辭而別

MySQL 客戶端發送一條 DML/DDL SQL 給服務端,服務端收到之后,就開始吭哧吭哧地執行。

SQL 執行完成之前,客戶端再沒有給服務端發送任何消息,就直接斷開連接了。

SQL 執行過程中,服務端并不能感知到連接已經斷開了,它還會一直賣力地執行 SQL。

SQL 執行完成之后,問題來了。

3、服務端怎么辦?

(1)先提交事務再回滾

如果服務端執行的是 DDL 語句,一條 SQL 執行完成之后,會自動提交事務。

如果服務端執行的是 DML? 語句,并且系統變量 auto_commit = on,一條 SQL 執行完成之后,也會自動提交事務。

因為服務端不知道客戶端已經斷開連接了,事務提交之后,它會把 SQL 執行結果發送給客戶端。

把結果發送給客戶端,執行的是 send() 系統調用,send() 有兩種行為:

行為一,如果 send() 把 SQL 執行結果寫入 socket 緩沖區,會返回寫入成功,此時,服務端還不會感知到客戶端已經斷開連接。

send() 執行成功之后,服務端認為這條 SQL 就告一段落了,會等待客戶端發送下一條命令。

由于客戶端已經斷開連接,從當前連接讀取下一條命令時會出錯。

此時,服務端會感知到客戶端已經斷開連接了。

行為二,如果 send() 直接把 SQL 執行結果發送給客戶端,服務端就能馬上感知到客戶端已經斷開連接了。

不管 send() 發生哪種行為,服務端都會感知到客戶端已經斷開連接了,無非早一點晚一點而已。

感知到連接斷開之后,服務端會回滾事務。

但是,由于執行 send() 之前,服務端已經把事務提交了,這里回滾事務并不會生效。

那么,最終結果就是:服務端對于數據的修改會被持久化,永久生效。

(2)回滾事務

如果服務端執行的是 DML 語句,并且用 begin 或 start transaction 顯式開啟了事務,一條 SQL 執行完成之后,不會自動提交事務,而是會等待客戶端發送下一條命令。

讀取下一條命令之前,服務端會執行 send() 系統調用,把當前 SQL 的執行結果發送給客戶端。

send() 有兩種行為:

?行為一,如果 send() 把 SQL 執行結果寫入 socket 緩沖區,會返回寫入成功,此時,服務端還不會感知到客戶端已經斷開連接。

send() 執行成功之后,服務端認為這條 SQL 就告一段落了,會等待客戶端發送下一條命令。

由于客戶端已經斷開連接,從當前連接讀取下一條命令時會出錯。

此時,服務端會感知到客戶端已經斷開連接了。

行為二,如果 send() 直接把 SQL 執行結果發送給客戶端,服務端就能馬上感知到客戶端已經斷開連接了。

不管 send() 發生哪種行為,服務端都會感知到客戶端已經斷開連接了,無非早一點晚一點而已。

感知到連接斷開之后,服務端會回滾事務?,由于執行 send() 之前,并沒有提交過事務,這里回滾事務會生效。

那么,最終結果就是:服務端對于數據的修改會被回滾,相當于沒有執行過 DML 操作。

4、總結

前面展開介紹了 MySQL 客戶端不辭而別之后,服務端進行的一系列操作,總結起來就 3 條:

第 1 條:如果服務端執行的是 DDL 語句,DDL 會執行成功。

第 2 條:如果服務端執行的是 DML? 語句,并且系統變量 auto_commit = on,DML 也會執行成功。

第 3 條:如果服務端執行的是 DML? 語句,并且用 begin、start transaction 顯式開啟了事務或者系統變量 auto_commit = off,事務會被回滾,DML 相當于沒有執行。

5、遺留問題

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

  • 先把 SQL 執行結果寫入 socket 緩沖區,緩沖區滿再發送給客戶端。
  • 直接把 SQL 執行結果發送給客戶端。

這兩種行為由操作系統內核決定,目前對于這個機制還沒有完全研究清楚,留待后續。

本文轉載自微信公眾號「一樹一溪」,可以通過以下二維碼關注。轉載本文請聯系一樹一溪公眾號。

責任編輯:姜華 來源: 一樹一溪
相關推薦

2023-11-12 21:58:41

Java“假死”

2023-03-06 08:01:56

MySQLCtrl + C

2009-08-21 15:59:22

服務端與客戶端通信

2009-08-21 16:14:52

服務端與客戶端通信

2011-09-09 09:44:23

WCF

2010-03-18 17:47:07

Java 多客戶端通信

2009-08-21 15:36:41

服務端與客戶端

2009-08-21 15:54:40

服務端與客戶端

2024-03-06 14:58:52

客戶端微服務架構

2010-11-19 14:22:04

oracle服務端

2015-01-13 10:32:23

RestfulWeb框架

2021-06-11 06:54:34

Dubbo客戶端服務端

2021-10-19 08:58:48

Java 語言 Java 基礎

2022-02-08 08:22:34

HTTP短連接TCP

2010-05-28 14:11:37

SVN1.6

2022-09-05 14:36:26

服務端TCP連接

2012-03-02 10:38:33

MySQL

2011-08-17 10:10:59

2021-09-22 15:46:29

虛擬桌面瘦客戶端胖客戶端

2021-10-14 08:39:17

Java Netty Java 基礎
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产美女自拍视频 | 国产午夜精品久久久久免费视高清 | 中文字字幕一区二区三区四区五区 | 黄免费在线 | 亚洲免费视频在线观看 | www.激情.com| 日韩成人中文字幕 | 四虎永久免费影院 | 91精品国产综合久久久密闭 | 三级视频在线观看 | 国产精品精品3d动漫 | 视频在线亚洲 | 毛片a级| 亚洲一区二区三区四区五区中文 | 99热在线免费 | 日日骑 | 欧美成人激情 | 日韩在线精品强乱中文字幕 | 色婷婷亚洲一区二区三区 | 亚洲国产一区二区三区在线观看 | 好好的日在线视频 | 欧美黄色精品 | 欧美久久国产 | 国产成人综合一区二区三区 | 亚洲欧美一区二区三区视频 | 影视先锋av资源噜噜 | av男人的天堂在线 | 久久成人午夜 | 一区二区三区日韩精品 | 99久久久久久久久 | 精品视频一区二区三区 | 金莲网 | 亚洲视频免费一区 | 欧美区日韩区 | 视频一区二区三区四区五区 | 免费久久视频 | 亚洲精品视频免费观看 | av香蕉| 日韩av在线免费 | 99久久久99久久国产片鸭王 | 蜜桃视频在线观看免费视频网站www |