MySQL有哪幾種數(shù)據(jù)存儲(chǔ)引擎?有什么區(qū)別?
MySQL支持多種數(shù)據(jù)存儲(chǔ)引擎,其中最常見(jiàn)的是MyISAM和InnoDB引擎??梢酝ㄟ^(guò)使用"show engines"命令查看MySQL支持的存儲(chǔ)引擎。
- 存儲(chǔ)方式:MyISAM引擎將數(shù)據(jù)和索引分別存儲(chǔ)在兩個(gè)不同的文件中,一個(gè)是.MYD文件用于存儲(chǔ)數(shù)據(jù),一個(gè)是.MYI文件用于存儲(chǔ)索引。而InnoDB引擎將數(shù)據(jù)和索引存儲(chǔ)在同一個(gè)文件中。
- 鎖機(jī)制:MyISAM引擎只支持表級(jí)鎖,即在對(duì)某個(gè)表進(jìn)行讀寫時(shí),會(huì)鎖住整個(gè)表,其他操作需要等待。而InnoDB引擎支持行級(jí)鎖,可以在并發(fā)訪問(wèn)時(shí)只鎖住需要操作的行,提高了并發(fā)性能。
- 事務(wù)支持:MyISAM引擎不支持事務(wù),而InnoDB引擎支持事務(wù)。事務(wù)是一種保證數(shù)據(jù)一致性和完整性的機(jī)制,可以將多個(gè)操作作為一個(gè)整體進(jìn)行提交或回滾。
- 外鍵支持:MyISAM引擎不支持外鍵約束,而InnoDB引擎支持外鍵約束。外鍵是用于維護(hù)表與表之間關(guān)系的一種機(jī)制,可以確保數(shù)據(jù)的一致性
什么是臟讀、幻讀、不可重復(fù)讀?要怎么處理?
臟讀、不可重復(fù)讀和幻讀是數(shù)據(jù)庫(kù)中的一些并發(fā)問(wèn)題。
臟讀是指一個(gè)事務(wù)在讀取另一個(gè)未提交事務(wù)的數(shù)據(jù)時(shí),如果未提交事務(wù)回滾了,則讀取到的數(shù)據(jù)是不一致的。
不可重復(fù)讀是指一個(gè)事務(wù)在相同的查詢條件下,多次讀取數(shù)據(jù)結(jié)果不一致。例如,事務(wù)A第一次讀取數(shù)據(jù)時(shí),事務(wù)B修改了相同的數(shù)據(jù)并提交,導(dǎo)致事務(wù)A第二次讀取時(shí)數(shù)據(jù)不一致。
幻讀是指一個(gè)事務(wù)在多次查詢中,由于其他事務(wù)插入或刪除數(shù)據(jù),導(dǎo)致查詢結(jié)果出現(xiàn)新增或減少的情況。
處理這些問(wèn)題的方法有幾種:
- 加鎖:可以使用數(shù)據(jù)庫(kù)提供的鎖機(jī)制,如行級(jí)鎖或表級(jí)鎖,來(lái)控制并發(fā)訪問(wèn),確保數(shù)據(jù)的一致性。但是加鎖會(huì)降低并發(fā)性能。需要自己根據(jù)業(yè)務(wù)需要添加共享鎖還是排它鎖。
- 調(diào)整事務(wù)隔離級(jí)別:數(shù)據(jù)庫(kù)提供了不同的事務(wù)隔離級(jí)別,如讀未提交、讀已提交、可重復(fù)讀和串行化??梢愿鶕?jù)具體情況選擇合適的隔離級(jí)別來(lái)避免并發(fā)問(wèn)題。
事務(wù)的基本特性和隔離級(jí)別有哪些?
事務(wù)的基本特性包括ACID:
- 原子性(Atomicity):一個(gè)事務(wù)中的所有操作要么全部成功提交,要么全部失敗回滾。事務(wù)是一個(gè)不可分割的工作單位,要么全部執(zhí)行,要么全部不執(zhí)行。
- 一致性(Consistency):事務(wù)執(zhí)行前后,數(shù)據(jù)庫(kù)的完整性約束沒(méi)有被破壞。事務(wù)的操作會(huì)將數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)轉(zhuǎn)換為另一個(gè)一致性狀態(tài)。
- 隔離性(Isolation):并發(fā)執(zhí)行的事務(wù)之間應(yīng)該相互隔離,一個(gè)事務(wù)的執(zhí)行不應(yīng)該被其他事務(wù)干擾。隔離性確保每個(gè)事務(wù)在并發(fā)環(huán)境中都能獨(dú)立執(zhí)行,不會(huì)受其他事務(wù)的影響。
- 持久性(Durability):一旦事務(wù)提交成功,其所做的修改將永久保存在數(shù)據(jù)庫(kù)中。即使發(fā)生系統(tǒng)崩潰或電源故障,數(shù)據(jù)庫(kù)也能夠恢復(fù)到事務(wù)提交后的狀態(tài)。
隔離級(jí)別是控制事務(wù)隔離性的一個(gè)參數(shù),常見(jiàn)的隔離級(jí)別包括:
- 讀未提交(Read Uncommitted):最低級(jí)別的隔離級(jí)別,允許一個(gè)事務(wù)讀取另一個(gè)事務(wù)未提交的數(shù)據(jù)。會(huì)出現(xiàn)臟讀問(wèn)題。
- 讀已提交(Read Committed):保證一個(gè)事務(wù)只能讀取到其他事務(wù)已經(jīng)提交的數(shù)據(jù),解決了臟讀問(wèn)題。但是可能會(huì)出現(xiàn)不可重復(fù)讀問(wèn)題。
- 可重復(fù)讀(Repeatable Read):保證在一個(gè)事務(wù)中多次讀取同一數(shù)據(jù)時(shí),得到的結(jié)果是一致的。解決了不可重復(fù)讀問(wèn)題。但是可能會(huì)出現(xiàn)幻讀問(wèn)題。
- 串行化(Serializable):最高級(jí)別的隔離級(jí)別,要求事務(wù)串行執(zhí)行,避免了幻讀問(wèn)題。但是會(huì)降低并發(fā)性能。
MySQL的鎖有哪些?什么是間隙鎖?
MySQL的鎖可以根據(jù)鎖的粒度進(jìn)行劃分,包括行鎖、表鎖和全局鎖。下面是對(duì)每種鎖的詳細(xì)說(shuō)明:
行鎖:InnoDB引擎支持行鎖,它的粒度很小,可以提供較好的并發(fā)性能,但是會(huì)消耗更多的資源。行鎖又可以細(xì)分為以下兩種:
- 共享鎖:使用
SELECT ** LOCK IN SHARE MODE
語(yǔ)句來(lái)獲取共享鎖,讀取操作期間可以共享,但會(huì)阻塞寫操作。 - 排它鎖:使用
SELECT ** FOR UPDATE
語(yǔ)句來(lái)獲取排它鎖,各種操作都會(huì)被阻塞,而且在執(zhí)行INSERT、DELETE、UPDATE語(yǔ)句時(shí)會(huì)自動(dòng)添加排它鎖。 - 自增鎖:當(dāng)涉及到自增字段時(shí),每次獲取自增值時(shí)都會(huì)進(jìn)行阻塞。需要注意的是,自增鎖與業(yè)務(wù)邏輯無(wú)關(guān)。
表鎖:直接鎖住整張表而不是單獨(dú)的行,表鎖消耗的資源比較少,但是鎖的粒度較大,導(dǎo)致并發(fā)性能較低。表鎖可以細(xì)分為以下兩種:
- 表共享鎖:多個(gè)會(huì)話可以同時(shí)獲取表的共享鎖,讀操作可以并發(fā)進(jìn)行,但是寫(INSERT、DELETE、UPDATE)會(huì)被阻塞。
- 表排它鎖:獲取表排它鎖的會(huì)話會(huì)阻塞其他會(huì)話的所有操作,包括讀和寫。
全局鎖:使用FLUSH TABLES WITH READ LOCK語(yǔ)句來(lái)獲取全局鎖,通常用于表數(shù)據(jù)備份等場(chǎng)景。
間隙鎖(Gap Lock)主要針對(duì)帶有索引的字段。例如,對(duì)于一個(gè)擁有user_id索引的user表(user_id, name),數(shù)據(jù)有(1,a)(4,b)(9,c),當(dāng)執(zhí)行UPDATE user SET name = d WHERE user_id = 5時(shí),會(huì)鎖定 5-9 之間的記錄(不包括自身)。而執(zhí)行UPDATE user SET name = 5 WHERE user_id = 4時(shí),則是記錄鎖,只鎖住一條記錄。
另一種類型是Next-Key鎖,它實(shí)際上是右側(cè)界的記錄鎖。對(duì)于上述user表的索引,Next-Key鎖會(huì)在(1, a)、(4, b)、(9, c)之間進(jìn)行鎖定。表示從左開(kāi)區(qū)間到右開(kāi)區(qū)間封閉,即( -∞, 1], (1, 4], (4, 9], (9, +∞)。這樣可以確保范圍內(nèi)的記錄都受到鎖的保護(hù)。
通過(guò)使用間隙鎖和Next-Key鎖,可以更精確地控制并發(fā)操作,提高數(shù)據(jù)庫(kù)的數(shù)據(jù)一致性和并發(fā)性能。
MySQL的索引結(jié)構(gòu)是什么樣的?聚簇索引和非聚簇索引又是什么?
MySQL是一種廣泛使用的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),具有多種存儲(chǔ)引擎和索引結(jié)構(gòu)可供選擇。存儲(chǔ)引擎是MySQL用來(lái)處理數(shù)據(jù)的核心組件,而索引結(jié)構(gòu)則用于提高數(shù)據(jù)檢索的效率。
在MySQL中,最常見(jiàn)和常用的存儲(chǔ)引擎是InnoDB和MyISAM。InnoDB是一個(gè)支持事務(wù)處理和行級(jí)鎖定的存儲(chǔ)引擎,適用于處理大量并發(fā)操作和高可靠性要求的應(yīng)用。而MyISAM則是一個(gè)更適合于讀寫不頻繁的應(yīng)用,它不支持事務(wù)處理,但速度較快。
索引結(jié)構(gòu)是用來(lái)加快數(shù)據(jù)檢索速度的一種數(shù)據(jù)結(jié)構(gòu)。
- B+樹(shù)索引是MySQL中最常見(jiàn)的索引結(jié)構(gòu)。它使用B+樹(shù)的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)索引值和對(duì)應(yīng)的數(shù)據(jù)行位置。非葉子節(jié)點(diǎn)只存儲(chǔ)索引值,葉子節(jié)點(diǎn)存儲(chǔ)索引值和對(duì)應(yīng)的數(shù)據(jù)行位置。B+樹(shù)索引的葉子節(jié)點(diǎn)按照索引值的順序排列,并且通過(guò)雙向鏈表連接,使得范圍查詢和最左前綴匹配查詢更高效。
- 哈希索引將索引值通過(guò)哈希函數(shù)映射為一個(gè)唯一的哈希值,并將哈希值和對(duì)應(yīng)的數(shù)據(jù)行位置存儲(chǔ)在哈希表中。哈希索引適用于等值查詢,但不支持范圍查詢和模糊查詢。
聚簇索引是索引值和表的數(shù)據(jù)存儲(chǔ)在一起的索引結(jié)構(gòu)。在InnoDB存儲(chǔ)引擎中,聚簇索引使用B+樹(shù)來(lái)實(shí)現(xiàn),葉子節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù)行的實(shí)際數(shù)據(jù)。一個(gè)表只能有一個(gè)聚簇索引,如果沒(méi)有顯式指定主鍵,那么會(huì)找第一個(gè)unique字段當(dāng)做主鍵索引,否則將會(huì)使用隱藏的rowid作為主鍵索引。
非聚簇索引是索引值和表的數(shù)據(jù)分開(kāi)存儲(chǔ)的索引結(jié)構(gòu)。在MyISAM存儲(chǔ)引擎中,每個(gè)索引都是一個(gè)獨(dú)立的文件,存儲(chǔ)索引值和對(duì)應(yīng)的數(shù)據(jù)行位置。一張表可以有多個(gè)非聚簇索引,比如表的普通索引。
MySQL的覆蓋索引和回表
覆蓋索引是指索引包含了查詢所需的所有字段,這樣在查詢時(shí)就可以直接使用索引中的數(shù)據(jù),而無(wú)需回表去讀取數(shù)據(jù)行。這種方式可以減少磁盤I/O操作,提高查詢性能。
當(dāng)一個(gè)查詢只需要從索引中獲取數(shù)據(jù)而不需要回表時(shí),就可以稱之為覆蓋索引查詢。在這種情況下,數(shù)據(jù)庫(kù)引擎只需要讀取索引頁(yè),而不需要再去讀取數(shù)據(jù)頁(yè),從而節(jié)省了磁盤I/O開(kāi)銷。
使用覆蓋索引可以提高查詢性能的原因是,索引通常比數(shù)據(jù)行小很多,所以從索引中讀取數(shù)據(jù)比從數(shù)據(jù)行中讀取數(shù)據(jù)更快。此外,覆蓋索引還可以減少內(nèi)存的使用,因?yàn)椴恍枰獙?shù)據(jù)行加載到內(nèi)存中進(jìn)行處理。
為了使用覆蓋索引,需要確保查詢語(yǔ)句中只包含索引字段,并且索引能夠滿足查詢條件和排序需求。如果查詢語(yǔ)句中包含了非索引字段,那么數(shù)據(jù)庫(kù)引擎仍然需要回表去讀取數(shù)據(jù)行,無(wú)法實(shí)現(xiàn)覆蓋索引查詢的優(yōu)化效果。
MySQL的集群是如何搭建的?讀寫分離是怎么做的?
MySQL的集群搭建通常使用主從復(fù)制的方式,并結(jié)合讀寫分離來(lái)提高數(shù)據(jù)庫(kù)的性能和可用性。
首先,在搭建MySQL集群之前,需要確定一個(gè)主節(jié)點(diǎn)和多個(gè)從節(jié)點(diǎn)。主節(jié)點(diǎn)負(fù)責(zé)處理寫操作,從節(jié)點(diǎn)負(fù)責(zé)處理讀操作。
在主節(jié)點(diǎn)接收到寫操作時(shí),會(huì)將修改的數(shù)據(jù)記錄到binlog日志中。binlog是二進(jìn)制日志,用于記錄數(shù)據(jù)庫(kù)的所有修改操作。從節(jié)點(diǎn)會(huì)定期讀取主節(jié)點(diǎn)的binlog日志,并將這些操作應(yīng)用到自己的數(shù)據(jù)庫(kù)中,實(shí)現(xiàn)主從數(shù)據(jù)的同步。
通常情況下,當(dāng)一個(gè)未提交的事務(wù)進(jìn)行操作數(shù)據(jù)時(shí),首先寫入到undolog,其次寫入redolog和binlog,但是提交事務(wù)之前并不會(huì)寫入磁盤,只是在內(nèi)存中,這種設(shè)計(jì)可以提高數(shù)據(jù)庫(kù)的性能,因?yàn)閷?shù)據(jù)寫入磁盤是比較耗時(shí)的操作,而將數(shù)據(jù)暫時(shí)保存在內(nèi)存中可以減少磁盤訪問(wèn)的次數(shù),從而提高數(shù)據(jù)庫(kù)的處理速度。
在讀寫分離的架構(gòu)中,還需要考慮主從復(fù)制的延遲問(wèn)題。由于主從復(fù)制是異步的,所以從節(jié)點(diǎn)上的數(shù)據(jù)可能不是實(shí)時(shí)同步的。可以通過(guò)設(shè)置合適的復(fù)制延遲時(shí)間來(lái)平衡數(shù)據(jù)的一致性和性能的需求。
半同步復(fù)制是MySQL主從復(fù)制的一種機(jī)制,它在傳輸binlog日志時(shí),主節(jié)點(diǎn)需要等待至少一個(gè)從節(jié)點(diǎn)確認(rèn)收到并寫入日志后才能繼續(xù)進(jìn)行下一步操作。
具體的工作流程如下:
- 當(dāng)主節(jié)點(diǎn)完成一次事務(wù)的提交后,它會(huì)將binlog日志發(fā)送給一個(gè)或多個(gè)從節(jié)點(diǎn)。
- 主節(jié)點(diǎn)會(huì)等待至少一個(gè)從節(jié)點(diǎn)將binlog日志寫入磁盤并發(fā)送一個(gè)確認(rèn)消息給主節(jié)點(diǎn)。
- 一旦主節(jié)點(diǎn)收到至少一個(gè)從節(jié)點(diǎn)的確認(rèn)消息,它才會(huì)認(rèn)為該次提交已經(jīng)完成,可以繼續(xù)進(jìn)行下一次操作。
談?wù)勅绾螌?duì)MySQL進(jìn)行分庫(kù)分表?多大數(shù)據(jù)量需要進(jìn)行分庫(kù)分表?分庫(kù)分表的方式和分片策略由哪些?分庫(kù)分表后,SQL語(yǔ)句的執(zhí)行流程是怎樣的?
分庫(kù)分表是一種常用的數(shù)據(jù)庫(kù)架構(gòu)優(yōu)化技術(shù),用于應(yīng)對(duì)數(shù)據(jù)規(guī)模不斷增長(zhǎng)的情況。分庫(kù)分表可以通過(guò)縱向拆分和橫向拆分兩種方式進(jìn)行。
- 縱向拆分是將不同的業(yè)務(wù)數(shù)據(jù)分開(kāi)存儲(chǔ)在不同的數(shù)據(jù)庫(kù)中,每個(gè)數(shù)據(jù)庫(kù)對(duì)應(yīng)一個(gè)業(yè)務(wù)。這樣可以有效避免單一數(shù)據(jù)庫(kù)數(shù)據(jù)量過(guò)大導(dǎo)致的性能問(wèn)題,但無(wú)法解決單個(gè)業(yè)務(wù)數(shù)據(jù)量過(guò)大的查詢問(wèn)題。
- 橫向拆分是將單個(gè)表中的數(shù)據(jù)按照某些字段進(jìn)行拆分,將數(shù)據(jù)分散存儲(chǔ)在多個(gè)表中。這樣可以減小單個(gè)表的數(shù)據(jù)量,提高查詢效率。常見(jiàn)的分片策略有按照范圍、按照哈希和按照取模等。
分庫(kù)分表會(huì)引入新的問(wèn)題,例如數(shù)據(jù)的拆分和合并、開(kāi)發(fā)和維護(hù)的復(fù)雜度增加等。因此,在選擇分庫(kù)分表之前,需要根據(jù)業(yè)務(wù)的增長(zhǎng)速度和數(shù)據(jù)量來(lái)判斷是否需要進(jìn)行分庫(kù)分表。根據(jù)阿里的開(kāi)發(fā)規(guī)范手冊(cè),一般在數(shù)據(jù)量達(dá)到500萬(wàn)或單個(gè)表文件大小增長(zhǎng)到2G時(shí),可以考慮進(jìn)行分庫(kù)分表的規(guī)劃。
通常,可以使用一些開(kāi)源的分庫(kù)分表中間件,如Mycat或ShardingSphere,來(lái)實(shí)現(xiàn)分庫(kù)分表功能。這些中間件支持DDL、DML等語(yǔ)句的執(zhí)行,能夠進(jìn)行排序、分組聚合等操作。但對(duì)于一些復(fù)雜的SQL語(yǔ)句,如子查詢,可能存在一定的限制。
SQL語(yǔ)句的執(zhí)行流程一般包括解析、優(yōu)化、路由、分片和歸并結(jié)果集等步驟。首先,數(shù)據(jù)庫(kù)會(huì)對(duì)SQL語(yǔ)句進(jìn)行解析,將其轉(zhuǎn)換成內(nèi)部數(shù)據(jù)結(jié)構(gòu)。然后,通過(guò)優(yōu)化器對(duì)SQL語(yǔ)句進(jìn)行優(yōu)化,生成最優(yōu)的執(zhí)行計(jì)劃。接下來(lái),根據(jù)分片策略,確定需要執(zhí)行的數(shù)據(jù)庫(kù)和表。然后,將SQL語(yǔ)句發(fā)送到相應(yīng)的數(shù)據(jù)庫(kù)節(jié)點(diǎn)執(zhí)行。最后,將執(zhí)行結(jié)果進(jìn)行歸并,返回給用戶文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-652567.html
總結(jié)
本次種子題目主要涵蓋了MySQL的存儲(chǔ)引擎和索引結(jié)構(gòu),如B+樹(shù)索引和哈希索引,以及覆蓋索引和回表的概念。此外,還包含了MySQL事務(wù)的ACID特性和隔離級(jí)別。另外,對(duì)MySQL主從集群中的binlog日志的執(zhí)行順序和作用進(jìn)行了討論。最后,還涉及了分庫(kù)分表和讀寫分離的概念。這些內(nèi)容涵蓋了MySQL數(shù)據(jù)庫(kù)的核心知識(shí)和重要技術(shù),不僅在面試中起到關(guān)鍵作用還對(duì)于優(yōu)化數(shù)據(jù)庫(kù)性能和應(yīng)用開(kāi)發(fā)都具有重要意義。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-652567.html
到了這里,關(guān)于MySQL面試題全解析:準(zhǔn)備面試所需的關(guān)鍵知識(shí)點(diǎn)和實(shí)戰(zhàn)經(jīng)驗(yàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!