系列綜述:
??目的:本系列是個(gè)人整理為了秋招面試
的,整理期間苛求每個(gè)知識(shí)點(diǎn),平衡理解簡(jiǎn)易度與深入程度。
??來源:材料主要源于拓跋阿秀、小林coding等大佬博客進(jìn)行的,每個(gè)知識(shí)點(diǎn)的修正和深入主要參考各平臺(tái)大佬的文章,其中也可能含有少量的個(gè)人實(shí)驗(yàn)自證。
??結(jié)語:如果有幫到你的地方,就點(diǎn)個(gè)贊和關(guān)注一下唄,謝謝???????。。?br> ??【C++】秋招&實(shí)習(xí)面經(jīng)匯總篇
??點(diǎn)此到文末驚喜??
基本篇
- 關(guān)系型數(shù)據(jù)庫
- 定義:是一種基于
ACID事務(wù)模型
的數(shù)據(jù)庫,采用表格形式
存儲(chǔ)數(shù)據(jù),通過表格中的關(guān)系連接
實(shí)現(xiàn)數(shù)據(jù)的查詢和管理。- 模型:采用ACID事務(wù)模型,強(qiáng)調(diào)數(shù)據(jù)的完整性和一致性
- 數(shù)據(jù)存儲(chǔ):采用表格形式存儲(chǔ)數(shù)據(jù),每一行表示一條記錄,每一列表示一個(gè)屬性,數(shù)據(jù)結(jié)構(gòu)清晰,易于理解和維護(hù)。
- 數(shù)據(jù)管理:通過表格中的關(guān)系連接進(jìn)行數(shù)據(jù)查詢和管理,主要有索引、視圖、觸發(fā)器等技術(shù)
- 定義:是一種基于
- 非關(guān)系型數(shù)據(jù)庫(NoSQL)
- 定義:是一種基于
BASE模型
的數(shù)據(jù)庫,采用多種形式
存儲(chǔ)數(shù)據(jù),通過分布式計(jì)算技術(shù)
實(shí)現(xiàn)高可擴(kuò)展性、高性能和高可用性- 模型:采用BASE模型,強(qiáng)調(diào)高可用性和性能的平衡
- 數(shù)據(jù)存儲(chǔ):采用多種形式的數(shù)據(jù)存儲(chǔ)模型,例如鍵值對(duì)、文檔、列族、圖形等
- 數(shù)據(jù)管理:通過分布式計(jì)算技術(shù),實(shí)現(xiàn)高可擴(kuò)展性、高性能和高可用性
- 定義:是一種基于
- MySQL 執(zhí)行一條 SQL語句的流程 / MySQL的內(nèi)部構(gòu)造
- 客戶端:發(fā)送請(qǐng)求與連接器進(jìn)行 TCP 三次握手建立
長(zhǎng)連接
- 服務(wù)層(Server)
- 連接器:主要用于連接管理,如連接的創(chuàng)建、運(yùn)行和銷毀等,以及身份驗(yàn)證和權(quán)限控制等問題
- 查詢緩存:存在則返回結(jié)果,不存在則繼續(xù)執(zhí)行
- 解析器:對(duì)SQL語句進(jìn)行進(jìn)行詞法分析、語法分析,并構(gòu)建語法樹
- 預(yù)處理器:檢查 SQL 查詢語句中的表或者字段是否存在,并展開
*
- 優(yōu)化器:確定SQL語句的執(zhí)行方案、選擇索引
- 執(zhí)行器:根據(jù)SQL語句讀取存儲(chǔ)引擎數(shù)據(jù),返回結(jié)果給客戶端
- 存儲(chǔ)引擎:負(fù)責(zé)數(shù)據(jù)的存儲(chǔ)和讀寫。是插件式的可以使用多種引擎,其中InnoDB是MySQL 默認(rèn)的存儲(chǔ)引擎
- 客戶端:發(fā)送請(qǐng)求與連接器進(jìn)行 TCP 三次握手建立
- 客戶端和數(shù)據(jù)庫的TCP長(zhǎng)連接
- 優(yōu)點(diǎn):減少連接建立和釋放的開銷
- 問題:如果一個(gè)連接長(zhǎng)時(shí)間沒有操作,MySQL會(huì)自動(dòng)斷開該連接
- 解決:
修改配置文件
中的默認(rèn)連接超時(shí)時(shí)間,通過心跳機(jī)制
定義維護(hù)或連接池
進(jìn)行管理連接
// 短連接 連接 mysql 服務(wù)(TCP 三次握手) 執(zhí)行sql 斷開 mysql 服務(wù)(TCP 四次揮手) // 長(zhǎng)連接 連接 mysql 服務(wù)(TCP 三次握手) 執(zhí)行sql 執(zhí)行sql 執(zhí)行sql .... 斷開 mysql 服務(wù)(TCP 四次揮手)
- MySQL數(shù)據(jù)庫文件結(jié)構(gòu)
- 數(shù)據(jù)庫文件存在于
/var/lib/mysql/ 自定義數(shù)據(jù)庫名
目錄下- db.opt:存儲(chǔ)當(dāng)前數(shù)據(jù)庫的默認(rèn)字符集和字符校驗(yàn)規(guī)則。
- 自定義表名.frm:存儲(chǔ)每個(gè)表的表結(jié)構(gòu)定義
- 自定義表名.ibd:存儲(chǔ)MySQL表的數(shù)據(jù)和索引
- 數(shù)據(jù)庫文件存在于
- 表空間文件
.ibd
的結(jié)構(gòu)- 段(segment)
- 索引段:存放 B + 樹的非葉子節(jié)點(diǎn)的區(qū)的集合;
- 數(shù)據(jù)段:存放 B + 樹的葉子節(jié)點(diǎn)的區(qū)的集合;
- 回滾段:存放的是回滾數(shù)據(jù)的區(qū)的集合
- 區(qū)(extent)
- 將連續(xù)的64個(gè)頁劃分到一個(gè)區(qū),鏈表中相鄰的頁的物理位置也相鄰
- 物理相鄰的頁可以使用順序 I/O,提高范圍查詢的掃描性能
- 頁(page)
- innoDB數(shù)據(jù)庫一次讀寫的單位是頁(16KB)
- 行(row)
- 數(shù)據(jù)庫表中的記錄都是按行(row)進(jìn)行存放的,每行記錄根據(jù)不同的行格式,有不同的存儲(chǔ)結(jié)構(gòu)。
- 段(segment)
- compact行格式(默認(rèn)格式)是如何存儲(chǔ)數(shù)據(jù)的?
- 控制部分
- 變長(zhǎng)字段長(zhǎng)度列表:逆序存儲(chǔ)變長(zhǎng)字段數(shù)據(jù)長(zhǎng)度
- NULL 值列表(非必須):逆序存儲(chǔ)代表列是否為NULL的二進(jìn)制位
- 記錄頭信息
- delete_mask :標(biāo)識(shí)此條數(shù)據(jù)是否被邏輯刪除(物理上還存在)
- next_record:下一條記錄的位置。指向的是下一條記錄的控制部分和數(shù)據(jù)部分之間的位置(方便向左讀控制部分,向右讀數(shù)據(jù)部分,提高cache命中率)
- record_type:表示當(dāng)前記錄的類型,0表示普通記錄,1表示B+樹非葉子節(jié)點(diǎn)記錄,2表示最小記錄,3表示最大記錄
- 數(shù)據(jù)部分
- row_id(主鍵標(biāo)識(shí)):沒有指定主鍵和唯一約束列時(shí),innodb會(huì)增加row_id 字段作為主鍵,占用 6 個(gè)字節(jié)。
- trx_id(事務(wù)標(biāo)識(shí)):標(biāo)識(shí)由那個(gè)事務(wù)生成,是必需的,占用6字節(jié)。
- roll_pointer(版本指針):指向該記錄的上一個(gè)版本,必需的,占用 7 個(gè)字節(jié)。
- 控制部分
- 在MySQL中varchar(n) 字段類型
- 組成:存儲(chǔ)頭部(變長(zhǎng)字段長(zhǎng)度列表 + NULL值列表)+ 數(shù)據(jù)部分
- 該字段類型一行最大為65535字節(jié)容量,其中n為字符個(gè)數(shù),具體大小與字符集有關(guān)
- MySQL 的行溢出
- 原因
- MySQL 中磁盤和內(nèi)存交互的基本單位是頁,一個(gè)頁的大小一般是 16KB
- 一個(gè)頁無法存儲(chǔ)一個(gè)大對(duì)象的一條記錄,會(huì)發(fā)生行溢出
- 解決:將溢出的數(shù)據(jù)存儲(chǔ)到溢出頁中,使用原頁中的20字節(jié)存儲(chǔ)溢出頁地址
- 原因
總結(jié):
數(shù)據(jù)庫的數(shù)據(jù)部分,由存放再磁盤上的三個(gè)文件組成:存儲(chǔ)字符集和字符校驗(yàn)規(guī)則的.opt文件、存儲(chǔ)表結(jié)構(gòu)的.frm文件、存儲(chǔ)表空間數(shù)據(jù)的.ibd文件。存儲(chǔ)表空間數(shù)據(jù)的.ibd文件有四個(gè)層次,分為為段、區(qū)、頁、行,其中,段有三種,一個(gè)是存放 B + 樹的非葉子節(jié)點(diǎn)的區(qū)集合的索引段,第二個(gè)是存放 B + 樹的葉子節(jié)點(diǎn)的區(qū)集合的數(shù)據(jù)段,第三個(gè)是存放的是回滾數(shù)據(jù)的區(qū)集合回滾段。每個(gè)區(qū)由64個(gè)物理地址連續(xù)的物理頁構(gòu)成,可以提高磁盤范圍查詢的順序IO性能。每個(gè)頁默認(rèn)為innodb一次讀寫的單位16KB。每個(gè)行存儲(chǔ)一條數(shù)據(jù)記錄,不同記錄具有不同的行格式。
索引篇
- 索引
- 定義:提升查詢性能的數(shù)據(jù)結(jié)構(gòu)。
- 優(yōu)點(diǎn)和缺點(diǎn)
- 加速查詢,適合
范圍查詢WHERE
、分組查詢GROUP BY 和 按屬性排序ORDER BY
- 將隨機(jī)IO變?yōu)轫樞騃O,將物理上不連續(xù)的記錄通過索引順序讀入物理上連續(xù)的緩存
- 索引的創(chuàng)建和維護(hù)需要耗費(fèi)時(shí)間,所以經(jīng)常更新的字段不適合建立索引
- 加速查詢,適合
- 索引分類
- 按「數(shù)據(jù)結(jié)構(gòu)」分類:B+tree索引、Hash索引、Full-text索引。
- 按「物理存儲(chǔ)」分類:聚集索引(聚簇索引)、非聚集索引(輔助索引)
- 按「字段特性」分類:主鍵索引、唯一索引、普通索引、前綴索引。
- 按「字段個(gè)數(shù)」分類:?jiǎn)瘟兴饕?、?lián)合索引。
- 其他:
- 每一種存儲(chǔ)引擎支持的索引類型不一定相同
- InnoDB 是在 MySQL 5.5 之后成為默認(rèn)的 MySQL 存儲(chǔ)引擎
- B+Tree 索引類型也是 MySQL 存儲(chǔ)引擎采用最多的索引類型。
- B+Tree 數(shù)據(jù)結(jié)構(gòu)(MySQL InnoDB 的默認(rèn)索引數(shù)據(jù)結(jié)構(gòu))
- 定義:B+樹可以分兩部分進(jìn)行理解
-
由非葉子結(jié)點(diǎn)組成
的多路平衡查找樹
用于快速的隨機(jī)查找
操作 -
由葉子結(jié)點(diǎn)組成
的按主鍵順序的雙鏈表
用于高效的數(shù)據(jù)的增刪操作
和基于范圍的順序查找
-
- 多路平衡查找樹
-
多路
表示是一棵多叉樹(m>2),每個(gè)非葉子結(jié)點(diǎn)由兩部分組成-
按主鍵順序的子節(jié)點(diǎn)索引鏈表
:每個(gè)子節(jié)點(diǎn)索引指向一個(gè)子節(jié)點(diǎn),且索引結(jié)點(diǎn)鍵值等于索引子節(jié)點(diǎn)的最小鍵值(類似目錄查找)。 -
最大和最小鍵值
:主要用于快速定位和過濾查詢請(qǐng)求的。
-
-
平衡
表示B+樹的每個(gè)子樹的高度是相等的,盡可能“矮胖” -
查找
表示B+樹的快速查找能力較強(qiáng)。-
相比B樹,非葉子結(jié)點(diǎn)不存放數(shù)據(jù)
:可以存放更多的索引,使得樹更加“矮胖”,極大減少比較耗時(shí)的I/O操作。 -
搜索復(fù)雜度為$O(log_dN)$
:當(dāng)最大分支數(shù)d大于100時(shí),千萬級(jí)數(shù)據(jù)量的查詢操作也只需做3~4
次的磁盤 I/O 操作,即樹的高度只有3~4層
。
-
-
- 雙鏈表
- 葉子結(jié)點(diǎn)的組成:一個(gè)葉子結(jié)點(diǎn)通常存儲(chǔ)多個(gè)數(shù)據(jù)記錄的物理地址,
頁目錄由槽組成
,索引數(shù)據(jù)記錄分組。數(shù)據(jù)記錄分組由數(shù)據(jù)記錄組成
,按主鍵順序存儲(chǔ)可由二分法進(jìn)行查找。 - 提高磁盤IO效率:頁是磁盤IO的基本單位(默認(rèn)為16KB),通常與葉子結(jié)點(diǎn)一一對(duì)應(yīng),但可以根據(jù)業(yè)務(wù)場(chǎng)景進(jìn)行調(diào)節(jié)
- 順序查找和增刪快:B+Tree 的層內(nèi)結(jié)點(diǎn)均
按指定鍵順序進(jìn)行雙鏈表鏈接
??梢愿咝M足數(shù)據(jù)的增刪操作
和基于范圍的順序查找
- 葉子結(jié)點(diǎn)的組成:一個(gè)葉子結(jié)點(diǎn)通常存儲(chǔ)多個(gè)數(shù)據(jù)記錄的物理地址,
- 定義:B+樹可以分兩部分進(jìn)行理解
- 按存儲(chǔ)方式劃分的索引:聚集索引(聚簇索引)和非聚集索引(輔助索引)
- 聚集索引
- 數(shù)據(jù)存儲(chǔ):聚集索引的
索引和數(shù)據(jù)存儲(chǔ)在一起
,在一個(gè)表中只能有一個(gè)聚集索引 - 性能:增刪慢,查詢快
- 數(shù)據(jù)存儲(chǔ):聚集索引的
- 非聚集索引
- 數(shù)據(jù)存儲(chǔ):非聚集索引的
索引和數(shù)據(jù)都是單獨(dú)存儲(chǔ)
,需要通過索引找到數(shù)據(jù)行 - 性能:增刪快,查詢慢
- 數(shù)據(jù)存儲(chǔ):非聚集索引的
- 聚集索引
- 按字段特性分類
- 主鍵索引
- 值唯一的聚簇索引,用于索引主鍵字段。一張表只能有一個(gè)主鍵索引
- 查詢性能高:值唯一,并按主鍵自動(dòng)排序,可以使用二分法進(jìn)行查找
- 唯一索引
- 值唯一的非聚簇索引,可以包含null值
- 普通索引
- 用于數(shù)據(jù)庫的查詢加速的非聚集索引,并且值可以重復(fù)
- 前綴索引
- 支持基于前綴搜索的模糊匹配, 空間復(fù)雜度低,搜索效率高。
- 主鍵索引
- 按字段個(gè)數(shù)分類*
- 單列索引:建立在單列上的索引
-
聯(lián)合索引
:建立在多列上的索引,遵循最左匹配原則
- 最左匹配原則:查詢條件中沒有聯(lián)合索引的第一個(gè)字段,則索引不會(huì)被使用。遇到范圍查詢(如 >、<)的時(shí)候會(huì)停止匹配,區(qū)間匹配需要掃描整個(gè)索引,而且這種操作代價(jià)相當(dāng)高,因此會(huì)使用其他方式。
- 下推優(yōu)化:在聯(lián)合索引遍歷過程中,對(duì)聯(lián)合索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數(shù)
- 區(qū)分度優(yōu)化:建立聯(lián)合索引時(shí),要把區(qū)分度大的字段排在前面,這樣區(qū)分度大的字段越有可能被更多的 SQL 使用到。
- MySQL 索引使用的注意事項(xiàng)
- 引起索引失效而導(dǎo)致全表查詢的操作
- 在列上使用
函數(shù)和計(jì)算
- 使用 != 或 not in或 <> 等
否定操作符
- 盡量避免
使用or
進(jìn)行條件連接 - 索引是
含NULL值列
-
查詢條件左右兩側(cè)類型不匹配
的時(shí)候會(huì)發(fā)生隱式轉(zhuǎn)換 -
like "%value"
匹配值第一個(gè)為%,會(huì)導(dǎo)致全表查詢
- 在列上使用
-
復(fù)合索引遵守最左匹配原則
,索引字段最好按區(qū)分度排序 - 刪除無效索引,增加熱點(diǎn)索引
- 覆蓋索引:直接將要查詢的數(shù)據(jù)以索引形式讀入內(nèi)存,減少磁盤IO
- 前綴索引優(yōu)化:只使用索引列數(shù)據(jù)的一部分,如長(zhǎng)字符串只使用前幾個(gè)字母作為前綴
- 引起索引失效而導(dǎo)致全表查詢的操作
事務(wù)篇
- 事務(wù)的四個(gè)特性ACID
- 原子性(Atomicity):一個(gè)事務(wù)中的所有操作,要么全做,要么全不做。如果在中間狀態(tài)發(fā)生錯(cuò)誤會(huì)回滾到開始狀態(tài)。
- 一致性(Consistency):事務(wù)執(zhí)行前后,數(shù)據(jù)均處于合法的狀態(tài)(完整性約束)
- 隔離性(Isolation):事務(wù)提交前,更新的數(shù)據(jù)對(duì)其他事務(wù)不可見。
- 持久性(Durability):已提交的事務(wù)的更新是持久的,發(fā)生故障可恢復(fù)
- 數(shù)據(jù)庫如何保證原子性
- 實(shí)現(xiàn):
Innodb 的回滾日志(undo log)
用于記錄事務(wù)執(zhí)行的反向操作
- 約束:
undo log必須先于數(shù)據(jù)持久化到磁盤
(謀而后動(dòng)),優(yōu)先保證回滾日志的完整性
- 實(shí)現(xiàn):
- 數(shù)據(jù)庫如何保證一致性
- 鎖機(jī)制:保證并發(fā)讀寫共享數(shù)據(jù)的正確性
- 觸發(fā)器機(jī)制:通過約束避免違反數(shù)據(jù)一致性的修改(類似斷言機(jī)制)
- 事務(wù)機(jī)制:通過事務(wù)執(zhí)行的原子性和隔離性保證修改操作的一致性
- 數(shù)據(jù)庫如何保證隔離性
- 使用
四種隔離級(jí)別
保證事務(wù)的隔離
- 使用
鎖機(jī)制
保證數(shù)據(jù)的訪問隔離
- 使用
MVCC(多版本并發(fā)控制
)保證并發(fā)的訪問隔離
- 使用
- 數(shù)據(jù)庫如何保證持久性
- undo log(回滾日志):存儲(chǔ)
執(zhí)行中事務(wù)的修改操作
,用于事務(wù)回滾的撤銷操作 - redo log(重做日志):循環(huán)存儲(chǔ)
已提交事務(wù)的修改操作
(循環(huán)區(qū)滿會(huì)被覆蓋),用于短時(shí)的故障恢復(fù) - bin log (歸檔日志):存儲(chǔ)
所有已提交事務(wù)的修改操作
(通常來源于重做日志),用于完整的數(shù)據(jù)恢復(fù)和主從復(fù)制
- undo log(回滾日志):存儲(chǔ)
- 事務(wù)的四個(gè)隔離級(jí)別(自頂向下性能下降,安全性增加)
-
未提交讀(read uncommitted)
- 概述:事務(wù)未提交,修改即可見(被其他事務(wù)讀到)
- 原理:事務(wù)開始時(shí),數(shù)據(jù)庫為該事務(wù)創(chuàng)建一個(gè)獨(dú)立工作區(qū)。對(duì)于讀操作,直接從數(shù)據(jù)庫中讀取。對(duì)于寫操作,修改到工作區(qū)中而不提交到數(shù)據(jù)庫中,其他并發(fā)事務(wù)讀取工作區(qū)中的數(shù)據(jù),但是如果該事務(wù)未提交而回滾,會(huì)導(dǎo)致其他并發(fā)事務(wù)的臟讀。
-
提交讀(read committed)
- 概述:事務(wù)提交時(shí),修改才可見
- 原理:事務(wù)
修改前先獲取寫鎖
,并將修改保存到事務(wù)日志中,然后再提交,從而保證其他事務(wù)只能讀取已經(jīng)提交的事務(wù)所修改的數(shù)據(jù)。
-
可重復(fù)讀(repeatable read)
- 概述:事務(wù)執(zhí)行期間多次讀到的相同數(shù)據(jù)是一致的,是MySQL InnoDB 引擎的默認(rèn)隔離級(jí)別;
- 原理:事務(wù)通過
讀寫鎖
共享訪問數(shù)據(jù),事務(wù)修改數(shù)據(jù)前要使用寫鎖,保證其他事務(wù)無法同時(shí)修改數(shù)據(jù)。事務(wù)讀取數(shù)據(jù)前加一個(gè)讀鎖,保證其他事務(wù)無法修改數(shù)據(jù)
-
串行化(serializable )
- 概述:并發(fā)事務(wù)的執(zhí)行結(jié)果與各事務(wù)按序單獨(dú)執(zhí)行結(jié)果相同(可線性化)
- 原理:MVCC可以通過為每個(gè)修改操作創(chuàng)建一個(gè)版本,并在讀取時(shí)根據(jù)版本來確定讀取的數(shù)據(jù)是否被修改過,從而實(shí)現(xiàn)串行化。在MVCC中,每個(gè)事務(wù)都可以看到自己開始之前的數(shù)據(jù)庫狀態(tài),但是不能看到其他事務(wù)的更新。
-
- 事務(wù)為什么要隔離 / 并發(fā)事務(wù)執(zhí)行導(dǎo)致的問題(嚴(yán)重程度自上而下)
-
臟讀
:A事務(wù)執(zhí)行更新數(shù)據(jù)操作后發(fā)生了回滾,而B事務(wù)讀到了更新后的數(shù)據(jù),但是由于A事務(wù)的回滾,導(dǎo)致B事務(wù)讀取數(shù)據(jù)和數(shù)據(jù)庫中的不一致。 -
不可重復(fù)讀
:事務(wù)針對(duì)同一條記錄
的前后兩次讀取結(jié)果不同 -
幻讀
:事務(wù)對(duì)于一條查詢語句
的前后兩次執(zhí)行結(jié)果不同
-
- 不同事務(wù)隔離級(jí)別的能力
- 在「讀未提交」隔離級(jí)別下,可能發(fā)生臟讀、不可重復(fù)讀和幻讀現(xiàn)象;
- 在「讀提交」隔離級(jí)別下,可能發(fā)生不可重復(fù)讀和幻讀現(xiàn)象,但是不可能發(fā)生臟讀現(xiàn)象;
- 在「可重復(fù)讀」隔離級(jí)別下,可能發(fā)生幻讀現(xiàn)象,但是不可能臟讀和不可重復(fù)讀現(xiàn)象;
- 在「串行化」隔離級(jí)別下,臟讀、不可重復(fù)讀和幻讀現(xiàn)象都不可能會(huì)發(fā)生。
鎖篇
- 全局鎖
- 鎖的生命周期:執(zhí)行
flush tables with read lock
加鎖,會(huì)話結(jié)束或者執(zhí)行unlock tables
會(huì)自動(dòng)釋放 - 加鎖后阻塞修改命令:
- 對(duì)
數(shù)據(jù)
的修改操作,比如 insert、delete、update等語句; - 對(duì)
表結(jié)構(gòu)
的修改操作,比如 alter table、drop table 等語句。
- 對(duì)
- 應(yīng)用場(chǎng)景
- 數(shù)據(jù)庫的邏輯備份,備份期間只讀,會(huì)影響業(yè)務(wù)。
- 解決方式:可重復(fù)讀隔離+MVCC——備份數(shù)據(jù)前創(chuàng)建快照,并鎖定數(shù)據(jù)庫只讀,其他事務(wù)執(zhí)行期間使用該快照進(jìn)行可重復(fù)讀隔離的數(shù)據(jù)處理,最后再將快照合并到數(shù)據(jù)庫中。(寫時(shí)拷貝,最后合并)
- 鎖的生命周期:執(zhí)行
- 表級(jí)鎖
- 表級(jí)讀寫鎖:讀鎖會(huì)阻塞寫,寫鎖會(huì)阻塞讀和寫。生命周期從加鎖到釋放鎖或會(huì)話結(jié)束,粒度較大影響并發(fā)性能
- 元數(shù)據(jù)鎖:對(duì)表操作加讀鎖,對(duì)表結(jié)構(gòu)操作加寫鎖。事務(wù)執(zhí)行期間一直持有,直到事務(wù)提交。由于執(zhí)行的寫優(yōu)先機(jī)制,如果出現(xiàn)寫鎖等待會(huì)阻塞其后的讀操作,導(dǎo)致線程棧溢出,所以對(duì)表結(jié)構(gòu)變更時(shí),先將其他執(zhí)行中的長(zhǎng)事務(wù)kill掉。
- 讀寫意向鎖:讀寫記錄先修改表的讀寫意向標(biāo)志位,方便其他事務(wù)快速判斷是否有事務(wù)正在讀寫表中數(shù)據(jù)。對(duì)表中的記錄加讀鎖前,先對(duì)整個(gè)表加意向讀鎖。對(duì)表中的記錄加寫鎖前,先對(duì)整個(gè)表加意向?qū)戞i??梢钥焖倥袛啾砝锸欠裼杏涗洷患渔i。
- AUTO-INC 鎖(5.1.22后變成字段鎖):插入數(shù)據(jù)前,被 AUTO_INCREMENT 修飾的字段加上輕量級(jí)鎖,然后給該字段賦值一個(gè)自增的值后即釋放,而不需要等待整個(gè)插入語句執(zhí)行完后才釋放鎖
- 行級(jí)鎖(innoDB支持,基于索引實(shí)現(xiàn))
- Record Lock:針對(duì)
一條記錄
的讀寫鎖 - Gap Lock:用于可重復(fù)讀隔離級(jí)別解決下幻讀問題,是對(duì)
一個(gè)范圍
的讀寫鎖 - Next-Key Lock:Record Lock + Gap Lock 的組合,
鎖定一個(gè)范圍,并且鎖定記錄本身
- Record Lock:針對(duì)
日志篇
- MySQL的關(guān)鍵日志
- undo log(回滾日志):保證事務(wù)執(zhí)行的原子性,主要用于事務(wù)回滾和MVCC。
- redo log(重做日志):實(shí)現(xiàn)最近完成事務(wù)的持久性,主要用于掉電等故障恢復(fù);
- bin log (歸檔日志):是 Server 層生成的日志,主要用于數(shù)據(jù)備份和主從復(fù)制;
- 回滾日志undo log
- 事務(wù)回滾
- 原理
- 記錄
未提交事務(wù)在數(shù)據(jù)庫中的修改操作
,若發(fā)生數(shù)據(jù)庫崩潰
或執(zhí)行ROLLBACK語句
,通過undo log將數(shù)據(jù)庫恢復(fù)到事務(wù)開始前的狀態(tài)。 - 先思后做:回滾日志必須先于數(shù)據(jù)持久化到磁盤
- 記錄
- 具體操作
-
插入
記錄時(shí),存儲(chǔ)記錄的主鍵
,回滾時(shí)只需要?jiǎng)h除主鍵對(duì)應(yīng)的記錄 -
刪除
記錄時(shí),存儲(chǔ)記錄的全部?jī)?nèi)容
,回滾時(shí)將該記錄再插入 -
更新
記錄時(shí),存儲(chǔ)記錄的舊值
,回滾時(shí)再更新為舊值
-
- 原理
- MVCC多版本并發(fā)控制原理
- 原理:通過undo log記錄的
數(shù)據(jù)版本鏈
保存事務(wù)對(duì)數(shù)據(jù)記錄修改的多個(gè)版本,每個(gè)事務(wù)通過隔離級(jí)別
和快照時(shí)間
選擇合適的版本讀取。 - 具體操作
- 「讀提交」隔離級(jí)別:事務(wù)執(zhí)行中對(duì)同一數(shù)據(jù)的select讀都會(huì)生成一個(gè)快照讀
- 「可重復(fù)讀」隔離級(jí)別:整個(gè)事務(wù)執(zhí)行期間使用同一個(gè)快照讀(select語句)
- 原理:通過undo log記錄的
- 事務(wù)回滾
- 重做日志 redo log(數(shù)據(jù)結(jié)構(gòu)和算法(原理和問題,解決方式))
- 基本概念:
- 原理概述:記錄
已提交事務(wù)的所有修改操作
,當(dāng)數(shù)據(jù)庫發(fā)生故障時(shí),系統(tǒng)會(huì)將重做日志中的操作重新執(zhí)行,進(jìn)行crash-safe(崩潰恢復(fù)),避免內(nèi)存斷電導(dǎo)致未刷盤的數(shù)據(jù)丟失 - WAL (Write-Ahead Logging)技術(shù):MySQL 的寫操作并不是立刻寫到磁盤上,而是先寫日志,然后在合適的時(shí)間再寫到磁盤上。
- 原理概述:記錄
- undo log 和redo log的區(qū)別
- 事務(wù)提交之前發(fā)生了崩潰,重啟后會(huì)通過 undo log 回滾事務(wù),事務(wù)提交之后發(fā)生了崩潰,重啟后會(huì)通過 redo log 恢復(fù)事務(wù)
- 執(zhí)行流程
- 執(zhí)行SQL語句,如果在Buffer Pool中未命中緩存頁,則將數(shù)據(jù)頁從磁盤加載到BufferPool中
- 修改緩存頁并置為臟頁,同時(shí)將當(dāng)前執(zhí)行事務(wù)的修改操作寫入redo log buffer中
- 數(shù)據(jù)庫選擇一個(gè)合適的時(shí)機(jī)將臟頁和redo log buffer刷盤
- redo log刷盤效率
- redo log buffer 是一個(gè)循環(huán)鏈表構(gòu)成的緩沖區(qū),
寫滿時(shí)
將最早寫入的記錄刷盤并覆蓋
- 寫滿阻塞問題
- 原因:如果系統(tǒng)并發(fā)量比較大,會(huì)導(dǎo)致redo log 緩沖文件經(jīng)常滿并要進(jìn)行刷盤而導(dǎo)致MySQL更新操作被阻塞
- 解決方式:通過調(diào)整
innodb_log_Buffer_size 參數(shù)
增加redo log容量(默認(rèn)16 MB)
- 刷盤方式:redo log刷盤是以追加方式的順序?qū)?,磁盤執(zhí)行效率高
- redo log buffer 是一個(gè)循環(huán)鏈表構(gòu)成的緩沖區(qū),
- redo log 刷盤時(shí)機(jī)(刷盤過多影響效率,刷盤過少影響安全)
- MySQL
正常關(guān)閉
時(shí); - 當(dāng) redo log buffer 中記錄的寫入量
大于
redo log buffer 內(nèi)存空間的一半
時(shí),會(huì)觸發(fā)落盤; - InnoDB 的后臺(tái)線程
每隔 1 秒
,將 redo log buffer 持久化到磁盤。 - 每次
事務(wù)提交
時(shí)都將緩存在 redo log buffer 里的 redo log 直接持久化到磁盤
- MySQL
- 基本概念:
- bin log
- 定義:MySQL 的 Server 層實(shí)現(xiàn)的日志,用于記錄已提交事務(wù)的修改操作。
- 寫入方式:binlog 是追加寫,寫滿一個(gè)文件,就創(chuàng)建一個(gè)新的文件繼續(xù)寫,保存全部日志
- 執(zhí)行流程
- 創(chuàng)建binlog cache:MySQL 中的每個(gè)線程都用于緩沖 binlog的 binlog cache緩存,由
binlog_cache_size 參數(shù)
控制,超過緩存大小就要暫存到磁盤。 - 提交時(shí)寫入:事務(wù)執(zhí)行過程中,先把修改記錄寫入binlog 的Server 層cache,事務(wù)提交的時(shí)候,再把 binlog cache中的完整事務(wù)執(zhí)行記錄寫到 binlog 文件中,并清空binlog cache(一個(gè)事務(wù)的binlog不能拆開,保證從庫執(zhí)行的原子性)
- 層級(jí)寫入:每個(gè)線程將自己 binlog cache增加事件頭區(qū)分,然后由binlog dump線程寫入同一個(gè) binlog 文件,最后通過fsync,將數(shù)據(jù)持久化到磁盤
- 創(chuàng)建binlog cache:MySQL 中的每個(gè)線程都用于緩沖 binlog的 binlog cache緩存,由
- 主從復(fù)制機(jī)制
- 原理:主數(shù)據(jù)庫將所有修改操作記錄到Binlog中,從數(shù)據(jù)庫請(qǐng)求并從主數(shù)據(jù)庫獲取Binlog并寫入本地的中繼日志relay log中,然后啟動(dòng)一個(gè)IO線程不斷讀取并更新從數(shù)據(jù)庫
- 作用
- 保證從數(shù)據(jù)庫和主數(shù)據(jù)庫的數(shù)據(jù)一致性,可用于數(shù)據(jù)備份、災(zāi)難恢復(fù)等
- 讀寫分離:寫數(shù)據(jù)時(shí)只寫主庫,在讀數(shù)據(jù)時(shí)只讀從庫,這樣即使寫請(qǐng)求會(huì)鎖表或者鎖記錄,也不會(huì)影響讀請(qǐng)求的執(zhí)行
- 兩階段提交協(xié)議(two phase commit protocol,2PC)
- 定義:是一種分布式事務(wù)一致性協(xié)議,
- 原理:將事務(wù)的提交分成兩個(gè)階段
- prepare表決階段:協(xié)調(diào)者將通知所有參與者準(zhǔn)備提交或取消事務(wù),在表決過程中,參與者將告知協(xié)調(diào)者自己的決策。
- commit 提交階段:協(xié)調(diào)者將基于第一個(gè)階段的投票結(jié)果進(jìn)行決策,當(dāng)且僅當(dāng)所有的參與者同意提交事務(wù)協(xié)調(diào)者才通知所有的參與者提交事務(wù),否則協(xié)調(diào)者將通知所有的參與者取消事務(wù)。參與者在接收到協(xié)調(diào)者發(fā)來的消息后將按事務(wù)提交順序執(zhí)行相應(yīng)的操作。
- 作用:保證事務(wù)提交后的redo log 和 binlog的一致性。 redo log 影響主庫的數(shù)據(jù),binlog 影響從庫的數(shù)據(jù),所以 redo log 和 binlog 必須保持一致才能保證主從數(shù)據(jù)一致。
- 兩段提交的問題及解決方式
- 磁盤 I/O 次數(shù)高:每個(gè)事務(wù)提交都會(huì)進(jìn)行兩次 fsync(刷盤),一次是 redo log 刷盤,另一次是 binlog 刷盤??赏ㄟ^ 組提交(group commit)機(jī)制將多個(gè)事務(wù)binlog刷盤操作合并成一次刷盤
- 鎖競(jìng)爭(zhēng)激烈:兩階段提交在「多事務(wù)」的情況下,需要加一個(gè)鎖來保證提交的日志提交順序的一致性。將提交階段進(jìn)行細(xì)分,減小鎖的粒度,提高并發(fā)度。
- MySQL 磁盤 I/O 很高,有什么優(yōu)化的方法?
- 設(shè)置組提交的兩個(gè)參數(shù): binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 參數(shù),延遲 binlog 刷盤的時(shí)機(jī),從而減少 binlog 的刷盤次數(shù)。這個(gè)方法是基于
故意等待,成組提交
來實(shí)現(xiàn)的,因此可能會(huì)增加語句的響應(yīng)時(shí)間,但即使 MySQL 進(jìn)程中途掛了,也沒有丟失數(shù)據(jù)的風(fēng)險(xiǎn),因?yàn)?binlog 早被寫入到 page cache 了,只要系統(tǒng)沒有宕機(jī),緩存在 page cache 里的 binlog 就會(huì)被持久化到磁盤。 -
寫入內(nèi)核緩沖區(qū),異步提交
將 sync_binlog 設(shè)置為大于 1 的值(比較常見是 100~1000),表示每次提交事務(wù)都 write,但累積 N 個(gè)事務(wù)后才 fsync,相當(dāng)于延遲了 binlog 刷盤的時(shí)機(jī)。但是這樣做的風(fēng)險(xiǎn)是,主機(jī)掉電時(shí)會(huì)丟 N 個(gè)事務(wù)的 binlog 日志。 - 將 innodb_flush_log_at_trx_commit 設(shè)置為 2。表示每次事務(wù)提交時(shí),都只是緩存在 redo log buffer 里的 redo log 寫到 redo log 文件,注意寫入到「 redo log 文件」并不意味著寫入到了磁盤,因?yàn)椴僮飨到y(tǒng)的文件系統(tǒng)中有個(gè) Page Cache,專門用來緩存文件數(shù)據(jù)的,所以寫入「 redo log文件」意味著寫入到了操作系統(tǒng)的文件緩存,然后交由操作系統(tǒng)控制持久化到磁盤的時(shí)機(jī)。但是這樣做的風(fēng)險(xiǎn)是,主機(jī)掉電的時(shí)候會(huì)丟數(shù)據(jù)
- 設(shè)置組提交的兩個(gè)參數(shù): binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count 參數(shù),延遲 binlog 刷盤的時(shí)機(jī),從而減少 binlog 的刷盤次數(shù)。這個(gè)方法是基于
- 具體更新一條記錄 UPDATE t_user SET name = ‘xiaolin’ WHERE id = 1; 的流程如下:
- 執(zhí)行器負(fù)責(zé)具體執(zhí)行,會(huì)調(diào)用存儲(chǔ)引擎的接口,通過主鍵索引樹搜索獲取 id = 1 這一行記錄:
- 如果 id=1 這一行所在的數(shù)據(jù)頁本來就在 buffer pool 中,就直接返回給執(zhí)行器更新;
- 如果記錄不在 buffer pool,將數(shù)據(jù)頁從磁盤讀入到 buffer pool,返回記錄給執(zhí)行器。
- 執(zhí)行器得到聚簇索引記錄后,判斷更新前后數(shù)據(jù)是否相同,若相同則不繼續(xù)執(zhí)行,若不同則將更新前后的記錄都當(dāng)作參數(shù)傳給 InnoDB 層,讓 InnoDB 真正的執(zhí)行更新記錄的操作;
- InnoDB 層先將數(shù)據(jù)庫修改操作記錄到相應(yīng)的 undo log,因?yàn)檫@是更新操作,需要把被更新的列的舊值記下來,也就是要生成一條 undo log,undo log 會(huì)寫入 Buffer Pool 中的 Undo 頁面,不過在內(nèi)存修改該 Undo 頁面后,需要記錄對(duì)應(yīng)的 redo log。
- InnoDB 層開始更新記錄,會(huì)先更新內(nèi)存(同時(shí)標(biāo)記為臟頁),然后將記錄寫到 redo log 里面,這個(gè)時(shí)候更新就算完成了。為了減少磁盤I/O,不會(huì)立即將臟頁寫入磁盤,后續(xù)由后臺(tái)線程選擇一個(gè)合適的時(shí)機(jī)將臟頁寫入到磁盤。這就是 WAL 技術(shù),MySQL 的寫操作并不是立刻寫到磁盤上,而是先寫 redo 日志,然后在合適的時(shí)間再將修改的行數(shù)據(jù)寫到磁盤上。
- 在一條更新語句執(zhí)行完成后,然后開始記錄該語句對(duì)應(yīng)的 binlog,此時(shí)記錄的 binlog 會(huì)被保存到 binlog cache,并沒有刷新到硬盤上的 binlog 文件,在事務(wù)提交時(shí)才會(huì)統(tǒng)一將該事務(wù)運(yùn)行過程中的所有 binlog 刷新到硬盤。
- 事務(wù)提交(為了方便說明,這里不說組提交的過程,只說兩階段提交):
- prepare 階段:將 redo log 對(duì)應(yīng)的事務(wù)狀態(tài)設(shè)置為 prepare,然后將 redo log 刷新到硬盤;
- commit 階段:將 binlog 刷新到磁盤,接著調(diào)用引擎的提交事務(wù)接口,將 redo log 狀態(tài)設(shè)置為 commit(將事務(wù)設(shè)置為 commit 狀態(tài)后,刷入到磁盤 redo log 文件);
- 執(zhí)行器負(fù)責(zé)具體執(zhí)行,會(huì)調(diào)用存儲(chǔ)引擎的接口,通過主鍵索引樹搜索獲取 id = 1 這一行記錄:
內(nèi)存篇(Buffer Pool)
詳細(xì)解釋:MySQL中數(shù)據(jù)是以頁為單位,你查詢一條記錄,會(huì)從硬盤把一頁的數(shù)據(jù)加載出來,加載出來的數(shù)據(jù)叫數(shù)據(jù)頁,會(huì)放入到Buffer Pool中。后續(xù)的查詢都是先從Buffer Pool中找,沒有命中再去硬盤加載(page fault?),減少硬盤IO開銷,提升性能。更新表數(shù)據(jù)的時(shí)候,也是如此,發(fā)現(xiàn)Buffer Pool里存在要更新的數(shù)據(jù),就直接在Buffer Pool里更新。然后會(huì)把“在某個(gè)數(shù)據(jù)頁上做了什么修改”記錄到重做日志緩存(redo log buffer)里,接著刷盤到redo log文件里。
- Buffer Pool緩存機(jī)制
- 前提: InnoDB 中的數(shù)據(jù)
以頁為基本單位
進(jìn)行磁盤和內(nèi)存的交互,一個(gè)頁的默認(rèn)大小為 16KB。 - 初始化:MySQL 啟動(dòng)時(shí),InnoDB 會(huì)為 Buffer Pool 申請(qǐng)一片連續(xù)的內(nèi)存空間。
默認(rèn)配置
下為128MB
,并默認(rèn)以16KB為單位大小劃分緩沖頁??赏ㄟ^調(diào)整innodb_buffer_pool_size
參數(shù)來設(shè)置 Buffer Pool 的大小,一般建議設(shè)置成可用物理內(nèi)存的 70%左右 - 訪問方式:查詢一條記錄,先查找緩存,若沒有則InnoDB會(huì)將
整個(gè)數(shù)據(jù)頁
加載到Buffer Pool中,通過索引你定位到具體數(shù)據(jù)頁,再使用頁目錄定位具體的數(shù)據(jù)記錄 - 內(nèi)存關(guān)系:MySQL 剛啟動(dòng)時(shí),虛擬內(nèi)存空間很大,而使用到的物理內(nèi)存空間卻很小,因?yàn)橹挥羞@些邏輯頁被訪問發(fā)生缺頁中斷,系統(tǒng)才會(huì)申請(qǐng)物理內(nèi)存,并建立虛擬地址和物理地址的映射關(guān)系。
- 前提: InnoDB 中的數(shù)據(jù)
- 原理
- 讀取數(shù)據(jù):若查詢的數(shù)據(jù)記錄在Buffer Pool命中,則直接使用,否則再去磁盤中讀取。(
先查緩存,命中再去磁盤讀
) - 修改數(shù)據(jù):如果數(shù)據(jù)記錄在 Buffer Pool命中,則直接修改并設(shè)置為臟頁,再在一個(gè)
合適的時(shí)機(jī)
將臟頁刷盤。
- 讀取數(shù)據(jù):若查詢的數(shù)據(jù)記錄在Buffer Pool命中,則直接使用,否則再去磁盤中讀取。(
- Buffer Pool的頁面管理方式
- 空閑鏈表:連接
空閑緩沖頁的控制塊的索引
的雙鏈表 - Flush鏈表:連接
臟頁的控制塊的索引
的雙鏈表,后臺(tái)線程就可以遍歷 Flush 鏈表,將臟頁寫入到磁盤 - LRU鏈表:每次將
即將訪問的頁
移動(dòng)到鏈表頭部,如果該頁不在鏈表中,則淘汰鏈表末尾頁 - 臟頁同時(shí)存在于 LRU 鏈表和 Flush 鏈表。
- 空閑鏈表:連接
- 簡(jiǎn)單的 LRU 算法并沒有被 MySQL 使用的原因
- 預(yù)讀失效
- 問題:由于空間局部性,會(huì)將要訪問的數(shù)據(jù)頁的相鄰頁面也加載到LRU鏈表首部,但可能并未被訪問導(dǎo)致緩存命中率下降
- 解決方式:劃分這兩個(gè)區(qū)域后,預(yù)讀的頁就只需要加入到 old 區(qū)域的頭部,當(dāng)頁被真正訪問的時(shí)候,才將頁插入 young 區(qū)域的頭部,默認(rèn)young 區(qū)域與 old 區(qū)域比例是 63:37,即不常訪問的old區(qū)域加載進(jìn)來的局部頁擁有更高的淘汰速度。
- Buffer Pool 污染(分類解決)
- 問題:一個(gè)掃描大量數(shù)據(jù)的SQL語句會(huì)將LRU內(nèi)的大量熱點(diǎn)數(shù)據(jù)淘汰,當(dāng)熱點(diǎn)數(shù)據(jù)再次被訪問時(shí),由于緩存未命中會(huì)產(chǎn)生大量磁盤IO,導(dǎo)致性能急速下降
- 解決方式:將進(jìn)入到 young 區(qū)域條件增加了一個(gè)停留在 old 區(qū)域的時(shí)間判斷,避免非熱點(diǎn)數(shù)據(jù)的進(jìn)入(目標(biāo)清晰)
- 預(yù)讀失效
- 臟頁什么時(shí)候會(huì)被刷入磁盤?
- 當(dāng)
redo log 日志
滿了的情況下,會(huì)主動(dòng)觸發(fā)臟頁刷新到磁盤; -
Buffer Pool 空間不足
時(shí),需要將一部分?jǐn)?shù)據(jù)頁淘汰掉,如果淘汰的是臟頁,需要先將臟頁同步到磁盤; - MySQL 認(rèn)為
空閑時(shí)
,后臺(tái)線程會(huì)定期將適量的臟頁刷入到磁盤; - MySQL
正常關(guān)閉
之前,會(huì)把所有的臟頁刷入到磁盤;
- 當(dāng)
- Buffer Pool 的主要數(shù)據(jù)結(jié)構(gòu)
其他之其他
- Innodb為什么要用自增id作為主鍵?
- 提高性能:按序插入的自增主鍵可以減少InnoDB存儲(chǔ)引擎中B+數(shù)的分裂和重建,提高插入數(shù)據(jù)效率
- 避免數(shù)據(jù)沖突:避免主鍵沖突造成的數(shù)據(jù)插入失敗
- 增加靈活性:方便對(duì)表的擴(kuò)展和優(yōu)化,是一種非業(yè)務(wù)主鍵
- MyISAM和InnoDB實(shí)現(xiàn)B樹索引方式的區(qū)別是什么?
- MyISAM數(shù)據(jù)文件和索引文件分離。僅支持表級(jí)鎖,適合讀操作多,并發(fā)度低的場(chǎng)景
- InnoDB數(shù)據(jù)和索引在同一個(gè)文件中。支持事務(wù)機(jī)制和行級(jí)鎖,擁有更強(qiáng)的并發(fā)處理能力
- 說一說Drop、Delete與Truncate的共同點(diǎn)和區(qū)別
- Drop操作:刪除整個(gè)表(包括表結(jié)構(gòu)),刪除速度快但無法回滾
- Delete操作:根據(jù)指定條件進(jìn)行刪除,會(huì)產(chǎn)生undo日志可以進(jìn)行回滾操作
- Truncate 刪除表中的所有數(shù)據(jù),但是會(huì)保留表結(jié)構(gòu)、索引和約束等元素
- MySQL如何進(jìn)行性能優(yōu)化
- 存儲(chǔ)引擎:根據(jù)業(yè)務(wù)場(chǎng)景選擇合適的存儲(chǔ)引擎和配置參數(shù)
- 數(shù)據(jù)結(jié)構(gòu):設(shè)計(jì)合適的數(shù)據(jù)庫結(jié)構(gòu),允許部分?jǐn)?shù)據(jù)冗余,并進(jìn)行分庫分表
- 局部性處理:對(duì)熱點(diǎn)數(shù)據(jù)使用緩存?zhèn)浞莺退饕?,使用主從讀寫分離
- 優(yōu)化SQL語句:避免使用 Select *,列出需要查詢的字段
- B+樹相比于B樹的優(yōu)點(diǎn)
- 順尋查找快:B樹順序查找需要進(jìn)行中序遍歷,而B+樹的數(shù)據(jù)按指定鍵順序以雙向鏈表形式存儲(chǔ)在葉子節(jié)點(diǎn)
- 查詢穩(wěn)定好:任何關(guān)鍵字的查找必須走一條從根結(jié)點(diǎn)到葉子結(jié)點(diǎn),所有關(guān)鍵字查詢的路徑長(zhǎng)度相同
- 磁盤IO次數(shù)低:B+樹索引節(jié)點(diǎn)可以存儲(chǔ)更多的索引指針,更加矮胖
- Hash樹適合唯一值查找,但是常見業(yè)務(wù)場(chǎng)景是一次查多值和順序查找
- 視圖和游標(biāo)
- 視圖:是一個(gè)邏輯上的虛擬表,由查詢語句定義,可以將多個(gè)表中的數(shù)據(jù)進(jìn)行組合
- 游標(biāo):是一個(gè)臨時(shí)的數(shù)據(jù)庫緩存對(duì)象,緩存查詢的結(jié)果集,游標(biāo)可以更方便的執(zhí)行結(jié)果集相關(guān)的操作
- 數(shù)據(jù)庫悲觀鎖和樂觀鎖的原理和應(yīng)用場(chǎng)景分別有什么?
- 悲觀鎖(先獲取鎖,再進(jìn)行業(yè)務(wù)操作):數(shù)據(jù)庫執(zhí)行SELECT … FOR UPDATE時(shí)會(huì)獲取被選中的數(shù)據(jù)行的行鎖
- 樂觀鎖:不對(duì)數(shù)據(jù)進(jìn)行加鎖,通過時(shí)間戳避免ABA問題
- MySQL索引類型
- 哈希索引:通過
哈希表
實(shí)現(xiàn)單條記錄
的快速查詢 - BTree索引:通過
B+樹
組織索引值,實(shí)現(xiàn)任意數(shù)據(jù)記錄
的查詢 - 全文索引(FULLTEXT ):對(duì)文本中的所有單詞建立索引,大大提高文本搜索效率
- RTREE索引:將空間數(shù)據(jù)分解成不同層級(jí)的矩形區(qū)域,并將矩形區(qū)域組織成樹形結(jié)構(gòu),處理高維數(shù)據(jù)可能出現(xiàn)維度災(zāi)難
- 哈希索引:通過
- 數(shù)據(jù)庫分表
- 作用:將表細(xì)粒度化,減少表單的訪問負(fù)載,提高查詢性能
- 分表策略
- 水平拆分:解決表中數(shù)據(jù)量太大的問題
- 取模分表:數(shù)據(jù)相對(duì)比較均勻,不容易出現(xiàn)熱點(diǎn)和并發(fā)訪問的瓶頸。
- 連續(xù)分表:按照時(shí)間維度進(jìn)行劃分
- 垂直拆分:解決表間的IO競(jìng)爭(zhēng)問題
- 將不同的表放在不同的服務(wù)器上
- 水平拆分:解決表中數(shù)據(jù)量太大的問題
- 問題:數(shù)據(jù)遷移和擴(kuò)容需要將表進(jìn)行匯總和排序,會(huì)有比較大的開銷
- 數(shù)據(jù)庫中有那些鍵的類型
- 超鍵:在關(guān)系中能唯一標(biāo)識(shí)元組的屬性集(在表中,元組表示一行,屬性表示一列)
- 候選鍵:可以唯一標(biāo)識(shí)每個(gè)元組的一組屬性,該組屬性中刪除任一個(gè)都無法唯一標(biāo)識(shí)了
- 主鍵:唯一標(biāo)識(shí)每個(gè)元組的一個(gè)或多個(gè)屬性集合
- 外鍵:在其他表中是主鍵,可以保證相關(guān)表的數(shù)據(jù)完整性
- 數(shù)據(jù)庫中的三大范式
- 1NF(原子性):不存在多值屬性,即每個(gè)屬性值不能再分
- 2NF(唯一性):1NF且不存在非主屬性對(duì)主鍵的部分依賴(依賴主鍵中的一部分)
- 3NF(主鍵決定一切):1NF且不存在非主屬性對(duì)主鍵的傳遞依賴(a依賴b,b依賴c,則c傳遞依賴于a)
- BCNF:所有屬性不存在傳遞依賴。BCNF一定是3NF
- MySQL中CHAR和VARCHAR的區(qū)別有哪些
- 存儲(chǔ)長(zhǎng)度:char是固定長(zhǎng)度,實(shí)際字符不足用空白字符填充;vachar只占用實(shí)際存儲(chǔ)長(zhǎng)度,不占用多余空間
- 訪問速度:char的訪問速度通常比較快(內(nèi)存對(duì)齊?)
- 數(shù)據(jù)庫結(jié)構(gòu)優(yōu)化
- 范式優(yōu)化: 比如消除冗余(節(jié)省空間。。)
- 反范式優(yōu)化:比如適當(dāng)加冗余等(減少join)
- 限定數(shù)據(jù)的范圍: 務(wù)必禁止不帶任何限制數(shù)據(jù)范圍條件的查詢語句。比如:我們當(dāng)用戶在查詢訂單歷史的時(shí)候,我們可以控制在一個(gè)月的范圍內(nèi)。
- 讀/寫分離: 經(jīng)典的數(shù)據(jù)庫拆分方案,主庫負(fù)責(zé)寫,從庫負(fù)責(zé)讀;
- 拆分表:分區(qū)將數(shù)據(jù)在物理上分隔開,不同分區(qū)的數(shù)據(jù)可以制定保存在處于不同磁盤上的數(shù)據(jù)文件里。這樣,當(dāng)對(duì)這個(gè)表進(jìn)行查詢時(shí),只需要在表分區(qū)中進(jìn)行掃描,而不必進(jìn)行全表掃描,明顯縮短了查詢時(shí)間,另外處于不同磁盤的分區(qū)也將對(duì)這個(gè)表的數(shù)據(jù)傳輸分散在不同的磁盤I/O,一個(gè)精心設(shè)置的分區(qū)可以將數(shù)據(jù)傳輸對(duì)磁盤I/O競(jìng)爭(zhēng)均勻地分散開。對(duì)數(shù)據(jù)量大的時(shí)時(shí)表可采取此方法。可按月自動(dòng)建表分區(qū)。
文章來源:http://www.zghlxwxcb.cn/news/detail-706296.html
??點(diǎn)此跳轉(zhuǎn)到首行??文章來源地址http://www.zghlxwxcb.cn/news/detail-706296.html
參考博客
- 版權(quán)規(guī)范
- 一文講清楚MySQL事務(wù)隔離級(jí)別和實(shí)現(xiàn)原理,開發(fā)人員必備知識(shí)點(diǎn)
- 小林coding
- 待定引用
- 待定引用
- 待定引用
- 待定引用
- 待定引用
到了這里,關(guān)于【數(shù)據(jù)庫】MySQL基礎(chǔ)知識(shí)全解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!