java面試中經(jīng)常會問到的mysql問題有哪些總結(jié)(基礎(chǔ)版)
前言
在Java面試中,MySQL作為最常用的關(guān)系型數(shù)據(jù)庫,是高頻考察點之一。問題主要圍繞基礎(chǔ)概念、索引優(yōu)化、事務(wù)與鎖、SQL性能、存儲引擎、高可用等核心維度展開,既考察理論理解,也重視實際問題排查能力。以下是高頻問題分類整理,附帶核心考察點和回答思路:
一、基礎(chǔ)概念與存儲引擎
這類問題側(cè)重考察對MySQL底層核心組件的理解,是后續(xù)優(yōu)化類問題的基礎(chǔ)。
| 高頻問題 | 核心考察點 | 回答思路(精簡版) |
|---|---|---|
| 1. MySQL有哪些常用存儲引擎?InnoDB和MyISAM的區(qū)別是什么? | 存儲引擎特性對比,尤其是事務(wù)、鎖、索引的差異 | 常用引擎:InnoDB(默認)、MyISAM、Memory等 核心區(qū)別: - 事務(wù):InnoDB支持ACID,MyISAM不支持; - 鎖粒度:InnoDB支持行鎖+表鎖,MyISAM只支持表鎖; - 索引:InnoDB的主鍵索引是聚簇索引,MyISAM是非聚簇索引; - 崩潰恢復(fù):InnoDB支持redo/undo日志恢復(fù),MyISAM不支持; - 外鍵:InnoDB支持外鍵,MyISAM不支持。 |
| 2. 什么是聚簇索引和非聚簇索引?InnoDB的聚簇索引有什么特點? | 索引物理存儲結(jié)構(gòu),理解InnoDB索引底層邏輯 | - 聚簇索引:索引文件與數(shù)據(jù)文件重合,索引葉子節(jié)點直接存儲數(shù)據(jù)(InnoDB的主鍵索引就是聚簇索引); - 非聚簇索引:索引文件與數(shù)據(jù)文件分離,葉子節(jié)點存儲“主鍵值”,需通過主鍵回表查數(shù)據(jù)(InnoDB的非主鍵索引、MyISAM所有索引都是非聚簇); - InnoDB特點:必須有聚簇索引(無主鍵則選唯一索引,再無則生成隱藏主鍵),查詢效率依賴主鍵設(shè)計(避免過長主鍵導(dǎo)致非聚簇索引膨脹)。 |
| 3. MySQL的字符集和排序規(guī)則是什么?utf8和utf8mb4的區(qū)別? | 字符集底層支持,避免實際開發(fā)中的亂碼/表情問題 | - 字符集:存儲字符的編碼規(guī)則(如utf8、gbk);排序規(guī)則:字符比較/排序的規(guī)則(如utf8_general_ci、utf8_bin); - 區(qū)別:utf8僅支持1-3字節(jié)字符(無法存儲emoji),utf8mb4支持1-4字節(jié)字符(可存儲emoji,是MySQL推薦的“真正utf8”)。 |
二、索引設(shè)計與優(yōu)化(高頻重點)
索引是MySQL性能優(yōu)化的核心,問題會圍繞“索引原理、設(shè)計原則、失效場景”展開,甚至會結(jié)合SQL案例考察。
- 索引的類型有哪些?(按功能/結(jié)構(gòu)分)
考察對索引分類的全面理解,避免只知道主鍵索引。
- 按功能分:
- 主鍵索引(PRIMARY KEY):唯一非空,一張表只能有一個,InnoDB中是聚簇索引;
- 唯一索引(UNIQUE):值唯一(允許NULL,多個NULL不沖突);
- 普通索引(INDEX):無約束,僅用于加速查詢;
- 聯(lián)合索引(復(fù)合索引):多列組合的索引(如
idx_name_age (name, age)),需遵循“最左前綴原則”;- 全文索引(FULLTEXT):用于文本內(nèi)容(如文章)的模糊查詢,MyISAM和InnoDB(5.6+)均支持。
- 聯(lián)合索引的“最左前綴原則”是什么?舉個例子說明。
聯(lián)合索引的核心規(guī)則,也是索引失效的高頻場景。
- 原則:聯(lián)合索引的查詢效率依賴“從左到右的列順序”,如果跳過左邊的列,索引會失效;
- 例子:聯(lián)合索引
idx_a_b_c (a, b, c)
- 有效查詢:
where a=1、where a=1 and b=2、where a=1 and b=2 and c=3;- 失效查詢:
where b=2(跳過a)、where b=2 and c=3(跳過a)、where a=1 and c=3(跳過b,僅a列走索引,c列無效)。
- 哪些情況會導(dǎo)致索引失效?(SQL編寫誤區(qū))
考察實際SQL優(yōu)化經(jīng)驗,避免寫出“走不了索引”的低效SQL。
- 索引列參與運算(如
where id+1=10,改為where id=9);- 索引列使用函數(shù)(如
where SUBSTR(name,1,3)='abc',改為前綴匹配name like 'abc%');- 索引列使用不等于(
!=、<>)、not in、is not null(可能導(dǎo)致全表掃描,除非數(shù)據(jù)量極?。?;- 字符串不加引號(如
where name=123,MySQL會隱式轉(zhuǎn)換為where CAST(name AS UNSIGNED)=123,觸發(fā)函數(shù)失效);- 模糊查詢以
%開頭(如name like '%abc',索引無法匹配前綴,失效;name like 'abc%'有效);- 聯(lián)合索引不滿足最左前綴原則(見上文)。
- 如何判斷一條SQL是否走了索引?怎么查看執(zhí)行計劃?
考察實際排查能力,而非僅停留在理論。
- 查看執(zhí)行計劃:使用
EXPLAIN + SQL語句(如EXPLAIN select * from user where id=1);- 關(guān)鍵字段判斷:
type:索引使用類型,從好到差為system > const > eq_ref > ref > range > index > ALL(ALL是全表掃描,需優(yōu)化;range是范圍查詢,如between,可接受);key:實際使用的索引名稱(若為NULL,表示未走索引);rows:MySQL預(yù)估掃描的行數(shù)(行數(shù)越少,效率越高)。
- 為什么不建議給表的所有字段建索引?
考察對索引“雙刃劍”的理解,避免過度建索引。
- 索引會占用額外磁盤空間(尤其是聚簇索引,數(shù)據(jù)量越大,索引文件越大);
- 增刪改(INSERT/DELETE/UPDATE)操作會維護索引(如插入數(shù)據(jù)時需調(diào)整B+樹),導(dǎo)致寫入性能下降;
- MySQL優(yōu)化器會選擇“最優(yōu)索引”,過多索引可能導(dǎo)致優(yōu)化器誤判,反而走低效索引。
三、事務(wù)與鎖(核心原理)
事務(wù)是數(shù)據(jù)庫保證數(shù)據(jù)一致性的基礎(chǔ),鎖是并發(fā)控制的核心,二者常結(jié)合考察。
- MySQL事務(wù)的ACID屬性是什么?分別如何保證?
事務(wù)的基本定義,需結(jié)合InnoDB的底層機制說明“如何保證”。
- A(原子性):事務(wù)要么全執(zhí)行,要么全回滾;由undo日志保證(記錄事務(wù)修改前的狀態(tài),回滾時恢復(fù));
- C(一致性):事務(wù)執(zhí)行前后數(shù)據(jù)總量一致(如轉(zhuǎn)賬,A減100,B必加100);由A、I、D共同保證;
- I(隔離性):多個事務(wù)并發(fā)執(zhí)行時,相互不干擾;由鎖機制 + MVCC(多版本并發(fā)控制)保證;
- D(持久性):事務(wù)提交后,數(shù)據(jù)永久保存;由redo日志保證(記錄事務(wù)修改后的狀態(tài),崩潰時重做)。
- MySQL的事務(wù)隔離級別有哪些?默認是哪個?各級別會出現(xiàn)什么問題?
隔離級別的核心是“并發(fā)控制的權(quán)衡”,需明確“問題場景”(臟讀、不可重復(fù)讀、幻讀)。
各級別對比(從低到高,隔離性增強,并發(fā)性能下降):
| 隔離級別 | 臟讀(讀未提交) | 不可重復(fù)讀(讀已提交) | 幻讀(重復(fù)讀時數(shù)據(jù)量變化) | 默認級別(MySQL) |
|---|---|---|---|---|
| Read Uncommitted(讀未提交) | 允許 | 允許 | 允許 | - |
| Read Committed(讀已提交) | 禁止 | 允許 | 允許 | - |
| Repeatable Read(可重復(fù)讀) | 禁止 | 禁止 | 禁止(InnoDB通過MVCC實現(xiàn)) | ?(默認) |
| Serializable(串行化) | 禁止 | 禁止 | 禁止 | - |
- 臟讀:讀了其他事務(wù)未提交的數(shù)據(jù)(如A事務(wù)改了name但未提交,B事務(wù)讀了這個未提交的name,A回滾后B讀的是“臟數(shù)據(jù)”);
- 不可重復(fù)讀:同一事務(wù)內(nèi),多次讀同一行數(shù)據(jù),結(jié)果不一致(如A事務(wù)第一次讀age=20,B事務(wù)改age=25并提交,A事務(wù)再次讀age=25);
- 幻讀:同一事務(wù)內(nèi),多次執(zhí)行同一范圍查詢,結(jié)果行數(shù)不一致(如A事務(wù)查
age<30有10行,B事務(wù)插入1行age=25并提交,A事務(wù)再次查有11行)。
- InnoDB的鎖有哪些類型?(按粒度/功能分)
考察對鎖機制的理解,避免混淆“行鎖”和“表鎖”的適用場景。
- 按粒度分:
- 表鎖:鎖定整個表,開銷小、加鎖快,但并發(fā)低(MyISAM默認,InnoDB也支持,如
LOCK TABLES user READ);- 行鎖:鎖定單行數(shù)據(jù),開銷大、加鎖慢,但并發(fā)高(InnoDB默認,基于索引實現(xiàn),無索引則退化為表鎖);
- 間隙鎖(Gap Lock):鎖定“索引區(qū)間”(如
where id between 10 and 20,鎖定10-20之間的間隙),防止插入數(shù)據(jù)導(dǎo)致幻讀(InnoDB Repeatable Read級別下生效);- 按功能分:
- 共享鎖(S鎖,讀鎖):多個事務(wù)可同時加S鎖,只能讀不能改(
select ... lock in share mode);- 排他鎖(X鎖,寫鎖):一個事務(wù)加X鎖后,其他事務(wù)不能加任何鎖(
update/delete/insert默認加X鎖,或select ... for update顯式加X鎖)。
- 什么是死鎖?如何避免死鎖?
并發(fā)場景下的常見問題,考察實際排查和預(yù)防能力。
- 死鎖:兩個或多個事務(wù)互相等待對方釋放鎖(如A事務(wù)鎖了id=1,等id=2;B事務(wù)鎖了id=2,等id=1);
- 避免方案:
- 統(tǒng)一事務(wù)內(nèi)鎖的獲取順序(如都先鎖id小的,再鎖id大的);
- 減少鎖的持有時間(如事務(wù)內(nèi)先查詢,最后集中執(zhí)行更新/刪除);
- 使用
innodb_deadlock_detect參數(shù)開啟死鎖檢測(MySQL默認開啟,檢測到死鎖后回滾“代價小”的事務(wù));- 避免長事務(wù)(長事務(wù)持有鎖時間久,增加死鎖概率)。
四、SQL性能優(yōu)化與問題排查
這類問題更貼近實際開發(fā),考察“如何寫出高效SQL”和“如何定位慢查詢”。
- 什么是慢查詢?nèi)罩??如何開啟和使用?
定位慢查詢的核心工具,必須掌握。
- 定義:記錄“執(zhí)行時間超過閾值”的SQL日志(默認閾值是10秒,可調(diào)整);
- 開啟方式(臨時生效,重啟失效):
sql set global slow_query_log = on; -- 開啟慢查詢?nèi)罩?set global slow_query_log_file = '/var/lib/mysql/slow.log'; -- 日志存儲路徑 set global long_query_time = 2; -- 閾值設(shè)為2秒(執(zhí)行超過2秒的SQL會被記錄)- 查看慢查詢數(shù)量:
show global status like '%slow_queries%';- 分析工具:使用
mysqldumpslow命令(MySQL自帶)分析日志,如mysqldumpslow -s r -t 10 /var/lib/mysql/slow.log(查看返回行數(shù)最多的前10條慢查詢)。
- 如何優(yōu)化一條慢查詢SQL?(通用步驟)
考察系統(tǒng)化的優(yōu)化思路,而非單一技巧。
- 查看執(zhí)行計劃:用
EXPLAIN判斷是否走索引、是否全表掃描、掃描行數(shù)是否過多;- 優(yōu)化索引:若未走索引,檢查是否符合索引設(shè)計原則(如避免函數(shù)/運算),必要時新增索引(優(yōu)先聯(lián)合索引,而非單字段索引);
- 優(yōu)化SQL語句:
- 避免
select *(只查需要的字段,減少數(shù)據(jù)傳輸和內(nèi)存消耗);- 避免
limit深分頁(如limit 10000, 20,MySQL會掃描10020行再丟棄前10000行,優(yōu)化為where id > 10000 limit 20,利用主鍵索引);- 避免子查詢(子查詢可能生成臨時表,改為join查詢,如
select * from user where id in (select user_id from order)改為select u.* from user u join order o on u.id = o.user_id);- 拆分大SQL(如批量插入,用
insert into user (id,name) values (1,'a'),(2,'b')代替多次單條插入);- 優(yōu)化表結(jié)構(gòu):如分表分庫(數(shù)據(jù)量過大時,單表超過1000萬行需考慮)、字段類型優(yōu)化(如用
int代替varchar存ID,用datetime代替varchar存時間)。
- MySQL的臨時表是什么?什么時候會產(chǎn)生臨時表?
臨時表是SQL執(zhí)行中的“隱形性能殺手”,考察對底層執(zhí)行邏輯的理解。
- 定義:MySQL在執(zhí)行SQL時臨時創(chuàng)建的內(nèi)存/磁盤表,用于存儲中間結(jié)果,執(zhí)行完后自動刪除;
- 產(chǎn)生場景:
- 子查詢(如
select * from (select id from user) as t);- 聯(lián)合查詢(
union,若用union all則不產(chǎn)生臨時表);group by/order by的字段不是索引列(需臨時表排序);distinct與order by組合(需臨時表去重+排序);- 優(yōu)化:盡量用join代替子查詢,確保
group by/order by的字段走索引,減少臨時表產(chǎn)生。
五、高可用與數(shù)據(jù)安全
針對中高級Java開發(fā),會考察MySQL的集群、備份、容災(zāi)方案。
- MySQL主從復(fù)制的原理是什么?有什么作用?
主從復(fù)制是MySQL高可用的基礎(chǔ),必須掌握核心流程。
- 作用:讀寫分離(主庫寫,從庫讀,減輕主庫壓力)、數(shù)據(jù)備份(從庫可作為備份,避免主庫故障丟失數(shù)據(jù));
- 原理(三步):
- 主庫(Master)將寫操作記錄到binlog(二進制日志) ;
- 從庫(Slave)啟動
IO線程,讀取主庫的binlog,寫入本地的relay log(中繼日志) ;- 從庫啟動
SQL線程,讀取relay log,執(zhí)行日志中的SQL,同步主庫數(shù)據(jù)。
- 主從復(fù)制可能出現(xiàn)延遲,如何解決?
主從延遲是實際生產(chǎn)中的常見問題,考察解決方案的合理性。
- 原因:主庫寫binlog、從庫IO線程拉取、SQL線程執(zhí)行,任一環(huán)節(jié)耗時都會導(dǎo)致延遲(如主庫寫入量大、從庫性能差);
- 解決方案:
- 優(yōu)化從庫:給從庫配置更高的CPU/內(nèi)存,確保從庫性能不低于主庫;
- 并行復(fù)制:開啟從庫多SQL線程(MySQL 5.7+支持
log_slave_updates和slave_parallel_workers參數(shù),并行執(zhí)行不同庫的SQL);- 減少大事務(wù):大事務(wù)執(zhí)行時間長,會導(dǎo)致從庫SQL線程阻塞,拆分大事務(wù)為小事務(wù);
- 讀寫分離優(yōu)化:對“實時性要求高”的讀請求(如用戶剛下單后查訂單),強制走主庫,避免讀從庫的延遲數(shù)據(jù)。
- 如何備份MySQL數(shù)據(jù)?有哪些備份方式?
數(shù)據(jù)安全的核心,考察對備份策略的理解。
- 按備份方式分:
- 物理備份:直接復(fù)制數(shù)據(jù)庫文件(如
mysqldump工具,適用于小數(shù)據(jù)量)、xtrabackup(Percona工具,適用于大數(shù)據(jù)量,支持增量備份);- 邏輯備份:導(dǎo)出SQL語句(如
select * into outfile,備份后可跨版本恢復(fù),但速度慢);- 按備份范圍分:
- 全量備份:備份整個數(shù)據(jù)庫(如每天凌晨全量備份);
- 增量備份:只備份上次備份后變化的數(shù)據(jù)(如每小時增量備份,減少備份時間和空間);
- 注意:備份后需驗證可用性(如恢復(fù)到測試環(huán)境,檢查數(shù)據(jù)是否完整),避免“備份無效”。
六、其他高頻細節(jié)問題
- MySQL的自增主鍵(AUTO_INCREMENT)有什么特點?會重復(fù)嗎?
- 特點:默認從1開始,每次增1,唯一標識行數(shù)據(jù),是InnoDB聚簇索引的默認選擇;
- 重復(fù)場景:主從復(fù)制時,主庫自增主鍵未同步到從庫,主庫宕機后從庫變主庫,可能導(dǎo)致新數(shù)據(jù)的自增ID與原主庫沖突(需通過
auto_increment_offset和auto_increment_increment配置主從自增步長,避免重復(fù))。
- MySQL的MVCC是什么?如何實現(xiàn)的?
- 定義:多版本并發(fā)控制,InnoDB實現(xiàn)“可重復(fù)讀”隔離級別的核心,允許“讀不加鎖、寫不阻塞讀”;
- 實現(xiàn)原理:通過
undo日志(保存數(shù)據(jù)歷史版本)、事務(wù)ID(標記事務(wù)先后)、Read View(事務(wù)啟動時的“快照”,決定能看到哪些版本的數(shù)據(jù))實現(xiàn)。
- 什么是MySQL的連接池?為什么要用連接池?常用的連接池有哪些?
- 定義:管理MySQL連接的“池化技術(shù)”,預(yù)先創(chuàng)建一定數(shù)量的連接,避免頻繁創(chuàng)建/關(guān)閉連接的開銷;
- 原因:TCP連接創(chuàng)建/關(guān)閉耗時(三次握手、四次揮手),連接池復(fù)用連接,提升并發(fā)性能;
- 常用連接池:HikariCP(Spring Boot默認,性能最優(yōu))、Druid(阿里開源,支持監(jiān)控和防SQL注入)、C3P0(老舊,性能較差)。
以上問題覆蓋了MySQL面試的90%以上高頻場景,建議結(jié)合實際項目經(jīng)驗理解(如“你項目中如何優(yōu)化過慢查詢”“如何解決主從延遲問題”),避免純理論記憶。
總結(jié)
到此這篇關(guān)于java面試中經(jīng)常會問到的mysql問題有哪些的文章就介紹到這了,更多相關(guān)java面試中mysql問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java操作Elasticsearch?rest-high-level-client?的基本使用
這篇文章主要介紹了Java操作Elasticsearch?rest-high-level-client?的基本使用,本篇主要講解一下?rest-high-level-client?去操作?Elasticsearch的方法,結(jié)合實例代碼給大家詳細講解,需要的朋友可以參考下2022-10-10
關(guān)于feign調(diào)用的參數(shù)傳遞問題(@RequestBody和@RequestParam)
這篇文章主要介紹了關(guān)于feign調(diào)用的參數(shù)傳遞問題(@RequestBody和@RequestParam),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
后端如何接收格式為x-www-form-urlencoded的數(shù)據(jù)
x-www-form-urlencoded格式是一種常見的HTTP請求數(shù)據(jù)格式,它將請求參數(shù)編碼為鍵值對的形式,以便于傳輸和解析,下面這篇文章主要給大家介紹了關(guān)于后端如何接收格式為x-www-form-urlencoded的數(shù)據(jù),需要的朋友可以參考下2023-05-05
spring項目如何配置多數(shù)據(jù)源(已上生產(chǎn),親測有效)
這篇文章主要介紹了spring項目如何配置多數(shù)據(jù)源(已上生產(chǎn),親測有效),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
java開發(fā)RocketMQ生產(chǎn)者高可用示例詳解
這篇文章主要為大家介紹了java開發(fā)RocketMQ生產(chǎn)者高可用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08

