《前后端面試題
》專欄集合了前后端各個知識模塊的面試題,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。
文章目錄
- 一、本文面試題目錄
- 61. 如何查看MySQL中的死鎖日志?
- 62. MySQL中什么是索引合并?
- 63. 如何在MySQL中實現行級鎖?
- 64. MySQL中`char`和`varchar`的區別?
- 65. 什么是MySQL的外鍵約束?如何創建外鍵?
- 66. MySQL中如何實現分頁查詢的優化?
- 67. 什么是MySQL的回表查詢?如何避免?
- 68. MySQL中`drop`、`truncate`和`delete`的區別?
- 69. 如何在MySQL中創建自增主鍵?
- 70. MySQL中如何處理并發插入問題?
- 71. MySQL中什么是覆蓋索引?如何創建?
- 72. MySQL中如何實現定時任務?
- 73. MySQL中如何查看表的結構?
- 74. MySQL中如何實現數據的導入和導出?
- 75. 什么是MySQL的分區表?如何創建分區表?
- 76. MySQL中如何查看和殺死慢查詢進程?
- 77. MySQL中如何實現表的復制?
- 78. 如何在MySQL中使用CASE表達式?
- 79. MySQL中的字符集轉換是如何工作的?
- 80. 在MySQL中如何進行表的重命名?
- 二、155道面試題目錄列表
一、本文面試題目錄
61. 如何查看MySQL中的死鎖日志?
InnoDB存儲引擎會記錄死鎖相關信息到錯誤日志中,可通過以下方式查看:
- 首先確定錯誤日志位置:執行
SHOW VARIABLES LIKE 'log_error';
,結果中的Value
即為錯誤日志路徑(如/var/log/mysql/error.log
)。 - 直接查看日志文件:使用
cat
或tail
等命令查看該文件,死鎖信息通常包含LATEST DETECTED DEADLOCK
關鍵字,日志中會詳細記錄死鎖發生時的事務、SQL語句、鎖定的資源等信息,幫助分析死鎖原因。
示例死鎖日志片段:
LATEST DETECTED DEADLOCK
------------------------
2023-10-01 10:00:00 0x7f1234567890
*** (1) TRANSACTION:
TRANSACTION 12345, ACTIVE 10 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 10, OS thread handle 140737354125056, query id 1234 localhost root updating
UPDATE orders SET status = 1 WHERE id = 100*** (2) TRANSACTION:
TRANSACTION 12346, ACTIVE 8 sec starting index read
mysql tables in use 1, locked 1
2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 11, OS thread handle 140737354132224, query id 1235 localhost root updating
UPDATE orders SET status = 2 WHERE id = 200
*** WE ROLL BACK TRANSACTION (2)
62. MySQL中什么是索引合并?
索引合并是MySQL優化器的一種策略,當查詢條件中涉及多個索引列時,優化器可能會將多個單列索引合并使用,以提高查詢效率。例如,當WHERE
子句中使用OR
連接兩個索引列條件時,MySQL可能會分別使用兩個索引查詢,再合并結果。
示例:
假設有表users
,id
和name
分別有單列索引,執行:
SELECT * FROM users WHERE id = 10 OR name = 'Alice';
優化器可能會分別使用id
索引和name
索引查詢,再將結果合并,此時EXPLAIN
的type
列會顯示index_merge
。
注意:索引合并并非總是最優,復雜的合并可能導致性能下降,此時可考慮創建聯合索引替代。
63. 如何在MySQL中實現行級鎖?
InnoDB通過索引實現行級鎖,只有通過索引條件檢索數據時,才會使用行級鎖;否則會使用表級鎖。
共享鎖(S鎖):允許事務讀取一行數據,加鎖方式為SELECT ... LOCK IN SHARE MODE;
,其他事務可加共享鎖,但不能加排他鎖。
示例:
-- 事務1加共享鎖
START TRANSACTION;
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;
-- 此時事務2可加共享鎖,但加排他鎖會阻塞
排他鎖(X鎖):允許事務更新或刪除一行數據,加鎖方式為SELECT ... FOR UPDATE;
或默認的DML操作(INSERT
/UPDATE
/DELETE
),其他事務不能加任何鎖。
示例:
-- 事務1加排他鎖
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE;
-- 此時事務2加共享鎖或排他鎖都會阻塞
64. MySQL中char
和varchar
的區別?
特性 | char | varchar |
---|---|---|
長度固定性 | 固定長度,不足補空格 | 可變長度,只存儲實際數據長度 |
存儲空間 | 占用固定空間(如char(10) 占10字節) | 額外1-2字節存儲長度,實際數據占n字節 |
處理速度 | 快(無需計算長度) | 稍慢(需處理長度信息) |
適用場景 | 固定長度數據(如手機號、身份證號) | 可變長度數據(如姓名、地址) |
示例:
char(10)
存儲"abc"時,實際存儲"abc "(補7個空格)。varchar(10)
存儲"abc"時,實際存儲"abc"(加1字節長度標識)。
65. 什么是MySQL的外鍵約束?如何創建外鍵?
外鍵約束用于保證兩個表之間的參照完整性,即子表的外鍵列值必須匹配主表的主鍵列值或為NULL。
創建外鍵的語法:
-- 主表(用戶表)
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL
);-- 子表(訂單表),外鍵關聯用戶表id
CREATE TABLE orders (id INT PRIMARY KEY AUTO_INCREMENT,user_id INT,order_no VARCHAR(20),-- 外鍵約束CONSTRAINT fk_orders_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE -- 主表記錄刪除時,子表關聯記錄也刪除ON UPDATE CASCADE -- 主表記錄更新時,子表關聯記錄也更新
);
外鍵作用:防止子表插入無效的關聯數據,確保數據一致性。
66. MySQL中如何實現分頁查詢的優化?
普通分頁(LIMIT offset, rows
)在offset
很大時效率低(需掃描大量數據后丟棄),優化方式如下:
- 基于主鍵的分頁(適用于主鍵有序):
-- 第1頁:LIMIT 0, 10
SELECT * FROM users WHERE id > 0 LIMIT 10;
-- 第2頁:以上一頁最后一條id為起點
SELECT * FROM users WHERE id > 10 LIMIT 10;
原理:通過主鍵過濾跳過前面的數據,避免全表掃描,效率極高。
- 使用索引覆蓋分頁:
若查詢只需要部分字段,可通過索引覆蓋避免回表,再關聯查詢完整數據:
-- 先通過索引獲取分頁的id
SELECT id FROM users ORDER BY create_time LIMIT 100000, 10;
-- 再通過id查詢完整數據(假設id為主鍵索引)
SELECT * FROM users WHERE id IN (...);
No. | 大劍師精品GIS教程推薦 |
---|---|
0 | 地圖渲染基礎- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】 |
1 | Openlayers 【入門教程】 - 【源代碼+示例 300+】 |
2 | Leaflet 【入門教程】 - 【源代碼+圖文示例 150+】 |
3 | MapboxGL 【入門教程】 - 【源代碼+圖文示例150+】 |
4 | Cesium 【入門教程】 - 【源代碼+綜合教程 200+】 |
5 | threejs 【中文API】 - 【源代碼+圖文示例200+】 |
6 | Shader 編程 【圖文示例 100+】 |
67. 什么是MySQL的回表查詢?如何避免?
回表查詢:當使用非聚簇索引(二級索引)查詢時,索引葉子節點只存儲索引鍵和主鍵,需通過主鍵到聚簇索引中查找完整數據,這個過程稱為回表。
示例:
表users
主鍵為id
,name
為二級索引,執行:
SELECT * FROM users WHERE name = 'Alice';
- 步驟1:通過
name
索引找到Alice
對應的主鍵id=10
。 - 步驟2:通過
id=10
到聚簇索引中查詢完整數據(回表)。
避免回表:使用索引覆蓋,即查詢的字段都包含在二級索引中,無需回表。
示例:創建聯合索引(name, age)
,查詢:
SELECT name, age FROM users WHERE name = 'Alice';
此時索引已包含所需字段,無需回表。
68. MySQL中drop
、truncate
和delete
的區別?
操作 | 性質 | 事務支持 | 自增ID重置 | 空間釋放 |
---|---|---|---|---|
DELETE | DML語句,逐行刪除 | 支持(可回滾) | 不重置 | 不釋放(需OPTIMIZE ) |
TRUNCATE | DDL語句,清空表 | 不支持(不可回滾) | 重置 | 釋放 |
DROP | DDL語句,刪除表結構 | 不支持 | - | 釋放 |
示例:
-- 刪除數據(可回滾)
DELETE FROM users WHERE age < 18;-- 清空表(不可回滾,自增ID重置)
TRUNCATE TABLE users;-- 刪除表(不可恢復)
DROP TABLE users;
69. 如何在MySQL中創建自增主鍵?
自增主鍵通過AUTO_INCREMENT
關鍵字實現,特點是自動生成唯一值,通常作為表的主鍵。
創建方式:
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, -- 自增主鍵name VARCHAR(50) NOT NULL
);
特性:
- 默認從1開始,每次插入自動+1。
- 若插入時指定
id
值,且該值未被使用,則會使用指定值,后續自增值為MAX(id) + 1
。 - 若刪除表中數據,自增值不會重置(除非
TRUNCATE
表)。
修改自增值起始值:
ALTER TABLE users AUTO_INCREMENT = 1000; -- 下次插入從1000開始
70. MySQL中如何處理并發插入問題?
并發插入可能導致數據一致性問題(如重復數據),解決方式如下:
- 使用唯一索引:對唯一字段創建唯一索引,防止重復插入。
-- 創建唯一索引
CREATE UNIQUE INDEX idx_username ON users(username);-- 插入時忽略重復數據
INSERT IGNORE INTO users (username) VALUES ('test');-- 插入時若重復則更新
INSERT INTO users (username, age) VALUES ('test', 20)
ON DUPLICATE KEY UPDATE age = 20;
- 使用事務和鎖:高并發場景下,通過
SELECT ... FOR UPDATE
加排他鎖防止并發插入。
START TRANSACTION;
-- 檢查數據是否存在(加鎖防止其他事務插入)
SELECT * FROM users WHERE username = 'test' FOR UPDATE;
-- 若不存在則插入
INSERT INTO users (username) VALUES ('test');
COMMIT;
71. MySQL中什么是覆蓋索引?如何創建?
覆蓋索引:指查詢的所有字段(SELECT
子句)都包含在索引中,無需回表查詢,可提高查詢效率。
創建方式:根據查詢字段創建包含這些字段的聯合索引。
示例:
頻繁執行查詢:
SELECT id, name, age FROM users WHERE name = 'Alice';
此時可創建聯合索引(name, age)
(id
為主鍵,自動包含在二級索引中),索引包含name
、age
和id
,滿足查詢需求,實現覆蓋索引。
72. MySQL中如何實現定時任務?
可通過EVENT
(事件)實現定時任務,需先開啟事件調度器:
-- 查看是否開啟
SHOW VARIABLES LIKE 'event_scheduler';
-- 開啟(臨時)
SET GLOBAL event_scheduler = ON;
-- 永久開啟需修改配置文件:event_scheduler = ON
創建定時任務示例:每天凌晨3點刪除logs
表中30天前的數據
DELIMITER //
CREATE EVENT clear_old_logs
ON SCHEDULE EVERY 1 DAY
STARTS '2023-10-01 03:00:00'
DO
BEGINDELETE FROM logs WHERE create_time < DATE_SUB(NOW(), INTERVAL 30 DAY);
END //
DELIMITER ;
管理事件:
-- 查看事件
SHOW EVENTS;-- 禁用事件
ALTER EVENT clear_old_logs DISABLE;-- 刪除事件
DROP EVENT clear_old_logs;
73. MySQL中如何查看表的結構?
常用命令:
DESCRIBE
(或DESC
):查看表字段信息
DESCRIBE users; -- 或 DESC users;
結果包含字段名、類型、是否為NULL、主鍵、默認值等。
SHOW CREATE TABLE
:查看表創建語句(包含索引、引擎等詳細信息)
SHOW CREATE TABLE users;
結果顯示CREATE TABLE
語句,可用于復制表結構。
INFORMATION_SCHEMA
查詢:更靈活的元數據查詢
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'users' AND TABLE_SCHEMA = 'mydb';
74. MySQL中如何實現數據的導入和導出?
導出數據:
- 使用
mysqldump
導出表結構和數據
# 導出整個數據庫
mysqldump -u root -p mydb > mydb.sql# 只導出表結構
mysqldump -u root -p -d mydb > mydb_struct.sql# 只導出數據
mysqldump -u root -p -t mydb > mydb_data.sql
- 使用
SELECT ... INTO OUTFILE
導出數據到文件
SELECT * FROM users INTO OUTFILE '/tmp/users.csv'
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
導入數據:
- 使用
SOURCE
命令導入SQL文件
SOURCE /path/to/mydb.sql;
- 使用
LOAD DATA INFILE
導入文件數據
LOAD DATA INFILE '/tmp/users.csv' INTO TABLE users
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
No. | 大劍師精品GIS教程推薦 |
---|---|
0 | 地圖渲染基礎- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】 |
1 | Openlayers 【入門教程】 - 【源代碼+示例 300+】 |
2 | Leaflet 【入門教程】 - 【源代碼+圖文示例 150+】 |
3 | MapboxGL 【入門教程】 - 【源代碼+圖文示例150+】 |
4 | Cesium 【入門教程】 - 【源代碼+綜合教程 200+】 |
5 | threejs 【中文API】 - 【源代碼+圖文示例200+】 |
6 | Shader 編程 【圖文示例 100+】 |
75. 什么是MySQL的分區表?如何創建分區表?
分區表:將大表按規則拆分為多個小的子表(分區),邏輯上是一個表,物理上是多個文件,可提高查詢效率(只掃描相關分區)。
常見分區類型:
- 范圍分區:按列值范圍分區(如按時間)。
- 列表分區:按列值枚舉分區(如按地區)。
- 哈希分區:按哈希函數結果分區。
創建范圍分區表示例(按create_time
分年度存儲):
CREATE TABLE orders (id INT PRIMARY KEY,order_no VARCHAR(20),create_time DATETIME
)
PARTITION BY RANGE (YEAR(create_time)) (PARTITION p2021 VALUES LESS THAN (2022),PARTITION p2022 VALUES LESS THAN (2023),PARTITION p2023 VALUES LESS THAN (2024),PARTITION p_other VALUES LESS THAN MAXVALUE
);
查詢2022年數據時,只掃描p2022
分區:
SELECT * FROM orders WHERE YEAR(create_time) = 2022;
76. MySQL中如何查看和殺死慢查詢進程?
- 查看當前進程:
-- 查看所有進程
SHOW PROCESSLIST;-- 查看完整信息(包括SQL語句)
SHOW FULL PROCESSLIST;
結果中Id
為進程ID,State
為狀態(如Sending data
表示執行中),Info
為執行的SQL。
- 殺死慢查詢進程:
-- 根據進程ID殺死
KILL 123; -- 123為要終止的進程Id
場景:當某條SQL長時間執行導致阻塞時,可通過SHOW PROCESSLIST
找到對應的Id
,再用KILL
終止。
77. MySQL中如何實現表的復制?
- 復制表結構和數據:
-- 方法1:基于查詢
CREATE TABLE users_copy AS SELECT * FROM users;-- 方法2:先復制結構,再插入數據
CREATE TABLE users_copy LIKE users; -- 復制結構(包括索引)
INSERT INTO users_copy SELECT * FROM users;
- 跨數據庫復制:
-- 復制到其他庫
CREATE TABLE db2.users_copy LIKE db1.users;
INSERT INTO db2.users_copy SELECT * FROM db1.users;
注意:CREATE TABLE ... AS SELECT
不會復制索引和約束,CREATE TABLE ... LIKE
會復制表結構、索引和約束。
78. 如何在MySQL中使用CASE表達式?
原理說明:
CASE表達式用于在SQL中實現條件邏輯,類似于其他編程語言中的if-else或switch語句。它允許根據條件返回不同的值,可以用于SELECT、WHERE、ORDER BY等子句中。
示例代碼:
-- 簡單CASE表達式
SELECT product_name,category,CASE categoryWHEN 'Electronics' THEN 'Tech'WHEN 'Clothing' THEN 'Apparel'ELSE 'Other'END AS category_group
FROM products;-- 搜索CASE表達式
SELECT order_id,total_amount,CASE WHEN total_amount > 1000 THEN 'High'WHEN total_amount > 500 THEN 'Medium'ELSE 'Low'END AS order_priority
FROM orders;
79. MySQL中的字符集轉換是如何工作的?
原理說明:
MySQL中的字符集轉換發生在數據存儲、檢索和比較過程中。當客戶端和服務器字符集不一致時,MySQL會自動進行轉換。轉換規則基于連接參數、表定義和列定義的字符集設置。
示例代碼:
-- 創建表時指定字符集
CREATE TABLE my_table (name VARCHAR(50) CHARACTER SET utf8mb4
) ENGINE=InnoDB DEFAULT CHARSET=latin1;-- 查看當前連接的字符集設置
SHOW VARIABLES LIKE 'character_set%';-- 修改連接字符集
SET NAMES utf8mb4;
80. 在MySQL中如何進行表的重命名?
原理說明:
MySQL提供了RENAME TABLE語句用于重命名表,也可以使用ALTER TABLE語句。RENAME TABLE更高效,支持原子性操作,可以同時重命名多個表。
示例代碼:
-- 使用RENAME TABLE語句
RENAME TABLE old_table TO new_table;-- 使用ALTER TABLE語句
ALTER TABLE old_table RENAME TO new_table;-- 批量重命名表
RENAME TABLE table1 TO new_table1,table2 TO new_table2;
二、155道面試題目錄列表
文章序號 | MySQL面試題155道 |
---|---|
1 | MySQL面試題及詳細答案155道(01-20) |
2 | MySQL面試題及詳細答案155道(20-40) |
3 | MySQL面試題及詳細答案155道(41-60) |
4 | MySQL面試題及詳細答案155道(61-80) |
5 | MySQL面試題及詳細答案155道(81-100) |
6 | MySQL面試題及詳細答案155道(101-120) |
7 | MySQL面試題及詳細答案155道(121-140) |
8 | MySQL面試題及詳細答案155道(141-155) |