Mysql實(shí)戰(zhàn)45講

01 | 基礎(chǔ)架構(gòu):一條SQL查詢語(yǔ)句是如何執(zhí)行的捶朵?

MySql 邏輯架構(gòu)圖

image.png

image.png

執(zhí)行 create table 建表的時(shí)候并淋,如果不指定引擎類型,默認(rèn)使用InnoDB兔毙。
不同的存儲(chǔ)引擎共用一個(gè)Server 層。

連接器
連接器負(fù)責(zé)跟客戶端建立連接、獲取權(quán)限叙量、維持和管理連接。

mysql -h$ip -P$port -u$user -p

一個(gè)用戶成功建立連接后品山,即使你用管理員賬號(hào)對(duì)這個(gè)用戶的權(quán)限做了修改,也不會(huì)影響已經(jīng)存在連接的權(quán)限涯呻。修改完成后,只有再新建連接才會(huì)使用新的權(quán)限設(shè)置市栗。

查看連接信息


image.png

客戶端如果太長(zhǎng)時(shí)間沒(méi)動(dòng)靜蛛淋,連接器就會(huì)自動(dòng)將它斷開(kāi)嘹悼。這個(gè)時(shí)間是由參數(shù) wait_timeout 控制的其监,默認(rèn)值是8小時(shí)抖苦。如果在連接被斷開(kāi)之后,客戶端再次發(fā)送請(qǐng)求的話,就會(huì)收到一個(gè)錯(cuò)誤提醒: Lost connection to MySQL server during query。

查詢緩存

image.png

image.png
mysql> select SQL_CACHE * from T where  id = 10

MySQL 8.0 版本直接將查詢緩存的整塊功能刪掉了伏伐。

分析器
詞法分析(識(shí)別關(guān)鍵字,操作堤器,表名,列名)
語(yǔ)法分析 (判斷是否符合語(yǔ)法)

優(yōu)化器
優(yōu)化器是在表里面有多個(gè)索引的時(shí)候,決定使用哪個(gè)索引府蛇;或者在一個(gè)語(yǔ)句有多表關(guān)聯(lián)(join)的時(shí)候妆距,決定各個(gè)表的連接順序塞颁。
優(yōu)化器階段完成后,這個(gè)語(yǔ)句的執(zhí)行方案就確定下來(lái)了,然后進(jìn)入執(zhí)行器階段。

執(zhí)行器
開(kāi)始執(zhí)行的時(shí)候动分,要先判斷一下你對(duì)這個(gè)表 T 有沒(méi)有執(zhí)行查詢的權(quán)限喇肋。如果沒(méi)有,就會(huì)返回沒(méi)有權(quán)限的錯(cuò)誤
印荔。如果命中查詢緩存殷绍,會(huì)在查詢緩存返回結(jié)果的時(shí)候,做權(quán)限驗(yàn)證牧牢。查詢也會(huì)在優(yōu)化器之前調(diào)用 precheck 驗(yàn)證權(quán)限。

如果有權(quán)限掌唾,就打開(kāi)表繼續(xù)執(zhí)行。打開(kāi)表的時(shí)候,執(zhí)行器就會(huì)根據(jù)表的引擎定義挽拔,去調(diào)用這個(gè)引擎提供的接口术裸。

在數(shù)據(jù)庫(kù)的慢查詢?nèi)罩局锌吹揭粋€(gè)rows_examined 的字段,表示這個(gè)語(yǔ)句執(zhí)行過(guò)程中掃描了多少行轰传,這個(gè)值就是在執(zhí)行器每次調(diào)用引擎獲取數(shù)據(jù)航的時(shí)候累加的。

在有些場(chǎng)景下倔既,執(zhí)行器調(diào)用一次恕曲,在引擎內(nèi)部則掃描了多行,因此引擎掃描行數(shù)跟rows_examined并不是完全相同的叉存。

02 | 日志系統(tǒng):一條SQL更新語(yǔ)句是如何執(zhí)行的码俩?

查詢語(yǔ)句的那一套流程,更新語(yǔ)句也是同樣會(huì)走一遍歼捏。

mysql> create table T(ID int primary key, c int);

mysql> update T set c=c+1 where ID=2;
  1. 執(zhí)行語(yǔ)句前要先連接數(shù)據(jù)庫(kù)稿存,這是連接器的工作。
  2. 在一個(gè)表上有更新的時(shí)候瞳秽,跟這個(gè)表有關(guān)的查詢緩存會(huì)失效瓣履,所以這條語(yǔ)句就會(huì)把表 T 上所有緩存結(jié)果都清空。
  3. 分析器會(huì)通過(guò)詞法和語(yǔ)法解析知道這是一條更新語(yǔ)句练俐。
  4. 優(yōu)化器決定要使用 ID 這個(gè)索引袖迎。
  5. 執(zhí)行器負(fù)責(zé)具體執(zhí)行,找到這一行腺晾,然后更新燕锥。

與查詢流程不一樣的是,更新流程還涉及兩個(gè)重要的日志模塊:redo log 和binlog悯蝉。

redo log

WAL 的全稱是 Write-Ahead Logging归形,它的關(guān)鍵點(diǎn)就是先寫日志,再寫磁盤鼻由,也就是先寫粉板暇榴,等不忙的時(shí)再寫賬本厚棵。


image.png
image.png
image.png
binlog

MySQL 整體來(lái)看,其實(shí)就有兩塊:一塊是 Server 層,它主要做的是 MySQL 功能層面的事情蔼紧;還有一塊是引擎層婆硬,負(fù)責(zé)存儲(chǔ)相關(guān)事宜。

粉板 redo log 是 InnoDB 引擎特有的日志奸例,而server層也有自己的日志彬犯,稱為 binlog(歸檔日志)。

redolog 與 binlog的區(qū)別:


image.png

有了對(duì)這兩個(gè)日志的概念性理解哩至,我們?cè)賮?lái)看執(zhí)行器和 InnoDB 引擎在執(zhí)行這個(gè)簡(jiǎn)單的 update 語(yǔ)句時(shí)的內(nèi)部流程躏嚎。


image.png
image.png

將 redo log 的寫入拆成了兩個(gè)步驟:prepare 和 commit,這就是"兩階段提交"菩貌。

由于 redo log 和 binlog 是兩個(gè)獨(dú)立的邏輯卢佣,如果不用兩階段提交,要么就是先寫完 redo log 再寫 binlog,或者采用反過(guò)來(lái)的順序箭阶。我們看看這兩種方式會(huì)有什么問(wèn)題虚茶。

image.png

可以看到,如果不使用“兩階段提交”仇参,那么數(shù)據(jù)庫(kù)的狀態(tài)就有可能和用它的日志恢復(fù)出來(lái)的庫(kù)的狀態(tài)不一致嘹叫。

binlog作用
  • 恢復(fù)數(shù)據(jù)庫(kù)(全量備份 + 備份時(shí)間點(diǎn)后的binglog)
  • 擴(kuò)容搭建備庫(kù)(全量備份 + 備份時(shí)間點(diǎn)后的binglog)
  • 同步數(shù)據(jù)
image.png

03 | 事務(wù)隔離:為什么你改了我還看不見(jiàn)?

簡(jiǎn)單來(lái)說(shuō)诈乒,事務(wù)就是要保證一組數(shù)據(jù)庫(kù)操作罩扇,要么全部成功,要么全部失敗

在 MySQL 中怕磨,事務(wù)支持是在引擎層實(shí)現(xiàn)的喂饥。MySQL 原生的 MyISAM 引擎就不支持事務(wù),這也是MyISAM 被 InnoDB 取代的重要原因之一肠鲫。
ACID(Atomicity员帮、Consistency、Isolation导饲、Durability捞高,即原子性、一致性渣锦、隔離性硝岗、持久性)。

image.png
image.png
image.png
mysql> show variables like 'transaction_isolation';

+-----------------------+----------------+

| Variable_name | Value |

+-----------------------+----------------+

| transaction_isolation | READ-COMMITTED |

+-----------------------+----------------+
image.png
image.png

你可以在 information_schema 庫(kù)的innodb_trx 這個(gè)表中查詢長(zhǎng)事務(wù)袋毙,比如下面這個(gè)語(yǔ)句查詢超過(guò)60s的事務(wù)

select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60

04 | 深入淺出索引(上)

索引的出現(xiàn)其實(shí)就是為了提高數(shù)據(jù)查詢的效率辈讶,就像書的目錄一樣。

索引的常見(jiàn)模型

  1. 哈希表
    哈希表是一種以鍵 - 值(key-value)存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu),輸入待查找的值即 key娄猫,就可以找到其對(duì)應(yīng)的值即 Value.
    用一個(gè)哈希函數(shù)把 key 換算成一個(gè)確定的位置贱除,然后把 把 value 放在數(shù)組的這個(gè)位置。
    多個(gè) key 值經(jīng)過(guò)哈希函數(shù)的換算媳溺,會(huì)出現(xiàn)同一個(gè)值的情況(哈希沖突)月幌。處理這種情況的一種方法是,拉出一個(gè)鏈表悬蔽。
    增刪改扯躺,等值查詢很快, 但因?yàn)椴皇怯行虻男ВK饕鰠^(qū)間查詢的速度是很慢的录语。
    哈希表這種結(jié)構(gòu)適用于只有等值查詢的場(chǎng)景,比如Memcached 及其他一些 NoSQL 引擎禾乘。

  2. 有序數(shù)組
    有序數(shù)組在等值查詢和范圍查詢場(chǎng)景中的性能就都非常優(yōu)秀澎埠。
    如果僅僅看查詢效率,有序數(shù)組就是最好的數(shù)據(jù)結(jié)構(gòu)了始藕。但是蒲稳,在需要更新數(shù)據(jù)的時(shí)候就麻煩了,你往中間插入一個(gè)記錄就必須得挪動(dòng)后面所有的記錄伍派,成本太高江耀。
    有序數(shù)組索引只適用于靜態(tài)存儲(chǔ)引擎。

  3. 二叉搜索樹(shù)
    二叉搜索樹(shù)的特點(diǎn)是:每個(gè)節(jié)點(diǎn)的左兒子小于父節(jié)點(diǎn)诉植,父節(jié)點(diǎn)又小于右兒子節(jié)點(diǎn)祥国。查詢復(fù)雜度是O(logN)。
    當(dāng)然為了維持 O(log(N)) 的查詢復(fù)雜度晾腔,你就需要保持這棵樹(shù)是平衡二叉樹(shù)舌稀。為了做這個(gè)保證,更新的時(shí)間復(fù)雜度也是O(logN)建车。

image.png

覆蓋索引

由于覆蓋索引可以減少樹(shù)的搜索次數(shù)扩借,顯著提升查詢性能,所以使用覆蓋索引是一個(gè)常用的性能優(yōu)化手段缤至。

最左前綴原則

極客時(shí)間版權(quán)所有: https://time.geekbang.org/column/article/0?cid=139

不只是索引的全部定義潮罪,只要滿足最左前綴,就可以利用索引來(lái)加速檢索领斥。這個(gè)最左前綴可以是聯(lián)合索引的最左 N 個(gè)字段嫉到,也可以是字符串索引的最左 M 個(gè)字符。
查詢條件匹配復(fù)合索引最左的N個(gè)字段月洛,就可以使用該聯(lián)合索引何恶。
字符串查詢條件可以根據(jù)字符串最左M個(gè)字符,來(lái)匹配索引嚼黔。

在建立聯(lián)合索引的時(shí)候细层,如何安排索引內(nèi)的字段順序惜辑?
第一原則是,如果通過(guò)調(diào)整順序疫赎,可以少維護(hù)一個(gè)索引盛撑,那么這個(gè)順序往往就是需要優(yōu)先考慮采用的。
例如捧搞,有a,b 聯(lián)合查詢的需求抵卫,又有b獨(dú)立查詢的需求,這時(shí)應(yīng)該建聯(lián)合索引(b,a),而不是(a,b) 胎撇。

索引條件下推(index condition pushdown)

MySQL 5.6 引入的索引下推優(yōu)化(index condition pushdown)介粘, 可以在索引遍歷過(guò)程對(duì)索引中包含的字段先做判斷,直接過(guò)濾掉不滿足條件的記錄晚树,減少回表次數(shù)姻采。
例如有聯(lián)合索引(a,b), 查詢條件是a=x and b=y and c=z, 在Mysql5.6前,先在聯(lián)合索引中找到a=x的所有記錄题涨,然后回表在主鍵索引中匹配b,c條件偎谁。利用索引下推則可以直接在索引(a,b)中匹配a,b 條件,減少回表的記錄數(shù)纲堵。

06 | 全局鎖和表鎖 :給表加個(gè)字段怎么有這么多阻礙巡雨?

image.png

image.png

同步過(guò)程中,如果加全局鎖席函,關(guān)聯(lián)的表數(shù)據(jù)(例如訂單铐望、余額)會(huì)有一致性問(wèn)題。

image.png
image.png
image.png
image.png

事務(wù)中的 MDL 鎖(讀鎖茂附、寫鎖)正蛙,在語(yǔ)句執(zhí)行開(kāi)始時(shí)申請(qǐng),但是語(yǔ)句結(jié)束后并不會(huì)馬上釋放营曼,而會(huì)等到整個(gè)事務(wù)提交后再釋放乒验。

image.png

07 | 行鎖功過(guò):怎么減少行鎖對(duì)性能的影響?

MySQL 的行鎖是在引擎層由各個(gè)引擎自己實(shí)現(xiàn)的蒂阱。但并不是所有的引擎都支持行鎖锻全,比如MyISAM引擎就不支持行鎖。不支持行鎖意味著并發(fā)控制只能使用表鎖录煤,對(duì)于這種引擎的表鳄厌,同一張表上任何時(shí)刻只能有一個(gè)更新在執(zhí)行,這會(huì)影響到業(yè)務(wù)并發(fā)度妈踊。InnoDB 是支持行鎖的了嚎,這也是 MyISAM 被 InnoDB替代的重要原因之一。

在 InnoDB 事務(wù)中,行鎖是在需要的時(shí)候才加上的歪泳,但并不是不需要了就立刻釋放萝勤,而是要等到事務(wù)結(jié)束時(shí)才釋放。這個(gè)就是兩階段協(xié)議夹囚。
如果你的事務(wù)中需要鎖多個(gè)行纵刘,要把最可能造成鎖沖突、最可能影響并發(fā)度的鎖盡量往后放荸哟。

死鎖和死鎖檢測(cè)

image.png
image.png
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瞬捕,隨后出現(xiàn)的幾起案子鞍历,更是在濱河造成了極大的恐慌,老刑警劉巖肪虎,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劣砍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡扇救,警方通過(guò)查閱死者的電腦和手機(jī)刑枝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)迅腔,“玉大人装畅,你說(shuō)我怎么就攤上這事〔琢遥” “怎么了掠兄?”我有些...
    開(kāi)封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)锌雀。 經(jīng)常有香客問(wèn)我蚂夕,道長(zhǎng),這世上最難降的妖魔是什么腋逆? 我笑而不...
    開(kāi)封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任婿牍,我火速辦了婚禮,結(jié)果婚禮上惩歉,老公的妹妹穿的比我還像新娘等脂。我一直安慰自己,他們只是感情好柬泽,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布慎菲。 她就那樣靜靜地躺著,像睡著了一般锨并。 火紅的嫁衣襯著肌膚如雪露该。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天第煮,我揣著相機(jī)與錄音解幼,去河邊找鬼抑党。 笑死,一個(gè)胖子當(dāng)著我的面吹牛撵摆,可吹牛的內(nèi)容都是我干的底靠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼特铝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼暑中!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起鲫剿,我...
    開(kāi)封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鳄逾,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后灵莲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體雕凹,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年政冻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枚抵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡明场,死狀恐怖汽摹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情榕堰,我是刑警寧澤竖慧,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站逆屡,受9級(jí)特大地震影響圾旨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜魏蔗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一砍的、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧莺治,春花似錦廓鞠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)漱贱。三九已至峦耘,卻和暖如春贩虾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工浪感, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昔头,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓影兽,卻偏偏與公主長(zhǎng)得像揭斧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子峻堰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容