MySQL 面試題系列(二)

在這里插入圖片描述

目錄

      • 1: SQL 中常見的 JOIN 類型有哪些?請分別說明其連接邏輯和適用場景。
      • 2: UNION 和 UNION ALL 有什么區別?它們各自的適用場景是什么?
      • 3: 什么是視圖 (View)?它的作用和優缺點是什么?
      • 4: 什么是索引 (Index)?它的作用是什么?MySQL 中有哪些常見的索引類型?
      • 5: 索引的優缺點是什么?在什么情況下適合創建索引,什么情況下不適合?
      • 6: 什么是事務 (Transaction)?及其四大特性 (ACID) 的具體含義是什么?
      • 7: 事務的隔離級別有哪些?每種隔離級別解決了哪些并發問題?
      • 8: MySQL 存儲引擎 InnoDB 和 MyISAM 的主要區別是什么?它們各自的適用場景是什么?
      • 9: SQL 注入是什么?如何防止 SQL 注入攻擊?
      • 10: 什么是數據庫范式 (Normal Forms)?請簡述 1NF, 2NF, 3NF 的概念和目的。


1: SQL 中常見的 JOIN 類型有哪些?請分別說明其連接邏輯和適用場景。

重點講解
JOIN 子句用于根據兩個或多個表中的相關列,將這些表的行組合起來。

  1. INNER JOIN (內連接)

    • 邏輯:只返回兩個表中都存在匹配關系的行。
    • 特點:匹配失敗的行不出現在結果集中。
    • 場景:查詢需要同時滿足兩個表關聯條件的數據,如查詢有訂單的用戶信息。
    • 示例
      SELECT u.username, o.order_id
      FROM users u
      INNER JOIN orders o ON u.id = o.user_id;
      
  2. LEFT JOIN (左連接,或 LEFT OUTER JOIN)

    • 邏輯:返回左表中的所有行,以及右表中與左表匹配的行。如果右表中沒有匹配,則右表列顯示 NULL
    • 特點:以左表為基準,保留左表所有數據。
    • 場景:查詢某表的所有數據,并嘗試關聯另一表的數據,例如查詢所有用戶及其訂單信息(即使有些用戶沒有訂單)。
    • 示例
      SELECT u.username, o.order_id
      FROM users u
      LEFT JOIN orders o ON u.id = o.user_id;
      
  3. RIGHT JOIN (右連接,或 RIGHT OUTER JOIN)

    • 邏輯:返回右表中的所有行,以及左表中與右表匹配的行。如果左表中沒有匹配,則左表列顯示 NULL
    • 特點:以右表為基準,保留右表所有數據。
    • 場景:查詢第二表的所有數據,并嘗試關聯第一表的數據。在實際中,RIGHT JOIN 通常可以用 LEFT JOIN 調換左右表位置來替代。
    • 示例
      SELECT u.username, o.order_id
      FROM users u
      RIGHT JOIN orders o ON u.id = o.user_id;
      
  4. FULL JOIN (全連接,或 FULL OUTER JOIN)

    • 邏輯:返回左表和右表中的所有行。如果左表中沒有匹配的右表行,右表列顯示 NULL;如果右表中沒有匹配的左表行,左表列顯示 NULL
    • 特點:合并所有數據,不強制匹配。
    • 場景:需要查看兩個表中所有可能的數據組合,即使沒有直接關聯。MySQL 目前不支持 FULL OUTER JOIN 語法,通常通過 LEFT JOINRIGHT JOINUNION 組合來實現。
    • 模擬示例 (MySQL)
      SELECT u.username, o.order_id
      FROM users u LEFT JOIN orders o ON u.id = o.user_id
      UNION
      SELECT u.username, o.order_id
      FROM users u RIGHT JOIN orders o ON u.id = o.user_id
      WHERE u.id IS NULL; -- 排除左連接中已包含的匹配項
      

核心對比

  • INNER JOIN:取交集。
  • LEFT JOIN:保留左表所有,右表不足補 NULL
  • RIGHT JOIN:保留右表所有,左表不足補 NULL
  • FULL JOIN:保留兩表所有,不足互補 NULL

實踐建議

  • 明確連接條件 (ON),避免笛卡爾積。
  • 根據業務需求選擇合適的 JOIN 類型。LEFT JOININNER JOIN 是最常用的。
  • JOIN 列建立索引是性能優化的關鍵。

2: UNION 和 UNION ALL 有什么區別?它們各自的適用場景是什么?

重點講解
UNIONUNION ALL 都用于合并兩個或多個 SELECT 語句的結果集。

  1. UNION

    • 邏輯:合并結果集,并自動去除重復行
    • 特點:會進行去重操作,因此性能開銷相對較大。
    • 場景:當你需要合并來自不同表或不同查詢條件的結果,并且確保結果集中沒有重復項時使用。例如,獲取兩個表中所有不同的用戶ID。
    • 示例
      SELECT city FROM customers
      UNION
      SELECT city FROM suppliers; -- 如果customers和suppliers都有 'New York',結果中只會出現一次
      
  2. UNION ALL

    • 邏輯:合并結果集,保留所有行,包括重復行
    • 特點:不進行去重操作,因此性能開銷較小,效率更高。
    • 場景:當你確信結果集中不會有重復行,或者即使有重復行也需要全部保留時使用。例如,從不同分區或歷史表中合并日志數據。
    • 示例
      SELECT city FROM customers
      UNION ALL
      SELECT city FROM suppliers; -- 如果customers和suppliers都有 'New York',結果中會根據原始表各出現一次
      

核心對比

  • UNION:去重,性能開銷大。
  • UNION ALL:不去重,性能開銷小。

使用要求

  • 所有 SELECT 語句中的列數必須相同。
  • 對應列的數據類型必須兼容。
  • 列的順序通常要一致。

實踐建議

  • 優先使用 UNION ALL:除非你明確需要去除重復行,否則為了性能考慮,總是優先選擇 UNION ALL
  • 在Java應用中,當需要合并不同業務邏輯下的數據列表時,可以考慮使用 UNION ALL 在數據庫層面直接獲取結果,減少應用層的合并和去重邏輯。

3: 什么是視圖 (View)?它的作用和優缺點是什么?

重點講解

定義:視圖是一個虛擬表,其內容由查詢定義。它不存儲實際的數據,而是存儲查詢語句。每次查詢視圖時,都會執行其定義中的SQL查詢來獲取數據。

作用

  1. 簡化復雜查詢:將一個復雜的 JOIN 或子查詢封裝成一個簡單的視圖,用戶可以直接查詢視圖而無需了解底層表的復雜結構。
  2. 數據安全和權限控制:可以只暴露部分列或行給特定用戶,從而限制用戶訪問底層敏感數據,提高安全性。用戶只能查詢視圖中定義的數據,而不是整個表。
  3. 數據抽象和邏輯獨立性:當底層表的結構發生變化時,如果視圖定義不變,基于視圖的應用程序通常不需要修改。視圖提供了一個穩定的接口。
  4. 提供自定義數據展示:將不同表的數據邏輯上整合,以滿足特定業務需求的數據展示。

優點

  • 簡化SQL操作:用戶無需編寫復雜SQL,直接查詢視圖即可。
  • 提高安全性:精細化權限管理,只授權視圖訪問權限。
  • 數據邏輯獨立性:對基表的修改可能不影響視圖用戶。
  • 提高可維護性:復雜邏輯集中在視圖定義中。

缺點

  • 性能開銷:每次查詢視圖都會執行底層的SQL,如果視圖定義復雜,可能會影響查詢性能。尤其是嵌套視圖會層層解析。
  • DML操作限制:某些復雜的視圖(如包含 GROUP BYUNIONDISTINCT 或多表 JOIN 的視圖)可能不支持 INSERT, UPDATE, DELETE 操作。
  • 難以調試:當視圖查詢出現性能問題時,排查底層SQL可能比較復雜。
  • 維護成本:如果基表結構頻繁變化,可能需要同步更新視圖定義。

示例

-- 創建一個視圖,顯示活躍用戶的用戶名、郵箱和創建時間
CREATE VIEW active_users_view AS
SELECT username, email, created_at
FROM users
WHERE status = 1;-- 查詢視圖 (如同查詢普通表)
SELECT username, email FROM active_users_view WHERE created_at > '2023-01-01';

實踐建議

  • 主要用于復雜的查詢簡化和安全控制。
  • 對于性能敏感的場景,應謹慎使用復雜視圖,或考慮將視圖結果定期物化到實際表中。
  • 在Java應用中,視圖常用于報表統計和權限隔離。

4: 什么是索引 (Index)?它的作用是什么?MySQL 中有哪些常見的索引類型?

重點講解

定義:索引是一種特殊的文件(或數據結構),它存儲了表中特定列的值,并對這些值進行排序,以加快查詢速度。它類似于書籍的目錄。

作用

  1. 顯著提高數據檢索速度:通過快速定位到包含查詢條件的數據行,避免全表掃描。
  2. 加快 ORDER BYGROUP BY 操作:索引中的數據是有序的,可以直接用于排序和分組,減少額外的排序開銷。
  3. 保證數據完整性:如 PRIMARY KEYUNIQUE 約束,它們底層都是通過唯一索引來實現的。

常見的索引類型

  1. PRIMARY KEY (主鍵索引)

    • 特點:一個表只能有一個,值必須唯一且非空。MySQL會自動為主鍵創建聚集索引(InnoDB)。
    • 作用:唯一標識記錄,是檢索最快的方式。
  2. UNIQUE INDEX (唯一索引)

    • 特點:索引列的值必須唯一,但允許有多個 NULL 值(每個 NULL 被視為不同的值)。
    • 作用:保證數據唯一性,并提高檢索速度。
  3. NORMAL INDEX (普通索引 / 非唯一索引)

    • 特點:最基本的索引,沒有任何限制,允許重復值。
    • 作用:提高查詢效率。
  4. FULLTEXT INDEX (全文索引)

    • 特點:用于對文本內容進行模糊匹配搜索,如文章標題、新聞內容。
    • 作用:優化文本搜索性能。傳統 LIKE '%keyword%' 無法使用普通索引,但全文索引可以。
    • 引擎限制:MyISAM 和 InnoDB(MySQL 5.6+)支持。
  5. COMPOSITE INDEX (復合索引 / 聯合索引)

    • 特點:在多個列上創建的索引,遵循“最左前綴原則”。
    • 作用:當查詢條件包含復合索引的左邊列時,索引才能生效。
    • 示例INDEX (col1, col2, col3),查詢 WHERE col1=?WHERE col1=? AND col2=? 會使用到索引,但 WHERE col2=? 則不會。

InnoDB 存儲引擎的索引實現

  • 聚集索引 (Clustered Index):InnoDB表的數據是依據主鍵聚集存儲的。聚集索引的葉子節點存儲的就是整行記錄。每個表只能有一個聚集索引(通常就是主鍵)。
  • 輔助索引 (Secondary Index / 非聚集索引):葉子節點不存儲整行數據,而是存儲指向對應行主鍵值的指針。通過輔助索引查詢數據時,需要先查到主鍵,再通過主鍵到聚集索引中查找整行數據(這個過程稱為回表)。

示例

-- 創建普通索引
CREATE INDEX idx_username ON users (username);-- 創建唯一索引
CREATE UNIQUE INDEX uk_email ON users (email);-- 創建復合索引
CREATE INDEX idx_category_price ON products (category, price);-- 創建全文索引
CREATE FULLTEXT INDEX ft_name_description ON articles (title, content);

5: 索引的優缺點是什么?在什么情況下適合創建索引,什么情況下不適合?

重點講解

優點

  1. 大大提高數據檢索速度:這是索引最核心和最重要的優點,能將全表掃描變為快速定位。
  2. 加快排序和分組操作:當 ORDER BYGROUP BY 子句中的列有索引時,可以避免額外的排序開銷。
  3. 約束數據完整性:主鍵和唯一索引強制列值的唯一性。
  4. 提高JOIN操作的效率:連接列上有索引可以顯著加速關聯查詢。

缺點

  1. 占用磁盤空間:索引本身是數據結構,需要額外的存儲空間。
  2. 降低DML操作性能:當對表進行 INSERT, UPDATE, DELETE 操作時,除了修改數據本身,還需要同時更新索引,這會增加維護成本和時間。
  3. 性能選擇開銷:MySQL在處理查詢時,需要評估是否使用索引以及使用哪個索引,這本身也有成本。

適合創建索引的場景

  1. 在大表上經常進行查詢且 WHERE 條件中頻繁使用的列:如用戶ID、訂單號、商品名稱。
  2. 作為主鍵的列:強制唯一性,并提供最快的查找。
  3. 需要在 JOIN 子句中連接的列:加快表之間的連接速度。
  4. ORDER BYGROUP BY 子句中頻繁使用的列:提高排序和分組效率。
  5. 篩選選擇性高的列:即列中不同值的數量很多(重復值少)。例如,性別這種只有兩三個值的列選擇性很低,不適合單獨建立索引。
  6. 需要使用 DISTINCT 關鍵字的列:索引可以幫助實現快速去重。

不適合創建索引的場景

  1. 表的數據量很小:全表掃描可能比使用索引更快或差不多。
  2. 經常進行 INSERT, UPDATE, DELETE 操作的表:索引維護成本高,可能抵消查詢帶來的好處。
  3. 列中都是重復值,選擇性很低:例如性別、布爾值類型。索引無法有效縮小搜索范圍。
  4. 不常在 WHEREORDER BYGROUP BYJOIN 中使用的列:建立了也用不上,白白增加存儲和維護成本。
  5. 數據類型是大文本 (如 TEXT, BLOB) 的列:雖然可以創建前綴索引,但通常不直接對整個列創建,或者考慮全文索引。
  6. 過多的索引:每個索引都會增加寫操作的開銷和存儲空間,過多的索引可能適得其反,導致優化器選擇困難。

實踐建議

  • "空間換時間"的策略:用磁盤空間和寫操作性能的犧牲來換取查詢性能的提升。
  • 平衡原則:根據實際業務的讀寫比例來決定是否創建索引。讀操作遠多于寫操作的表更適合索引。
  • 定期審查和優化:通過 EXPLAIN 分析SQL語句,檢查索引使用情況,刪除無效或冗余索引。
  • 復合索引的“最左前綴原則”:優化索引設計的重要依據。

6: 什么是事務 (Transaction)?及其四大特性 (ACID) 的具體含義是什么?

重點講解

定義:事務是一個操作序列,這些操作被視為一個邏輯工作單元。它要么全部成功提交(Commit),要么全部失敗回滾(Rollback)。

四大特性 (ACID)

  1. 原子性 (Atomicity)

    • 含義:事務是一個不可分割的最小工作單元,其中的所有操作要么全部完成,要么全部不完成。如果事務中的任何一個操作失敗,那么整個事務都會被回滾到事務開始前的狀態,已完成的操作也會被撤銷。
    • 例子:銀行轉賬,從A賬戶扣錢和給B賬戶加錢必須同時成功或同時失敗。如果扣錢成功但加錢失敗,則扣錢操作也應回滾。
  2. 一致性 (Consistency)

    • 含義:事務執行前后,數據庫從一個合法狀態(consistent state)轉換到另一個合法狀態。這意味著事務必須遵守所有的預定義規則和約束(如主鍵唯一性、外鍵參照完整性、CHECK約束等)。
    • 例子:轉賬前后,總金額不變;插入數據后,表的主鍵仍然是唯一的。
  3. 隔離性 (Isolation)

    • 含義:并發執行的各個事務之間互不干擾,一個事務的中間狀態對其他事務是不可見的。從并發事務分離的角度看,就好像各個事務是按順序(串行)執行的。
    • 例子:A、B兩人同時查詢銀行賬戶余額,無論他們查詢的順序如何,他們看到的數據都應該是事務開始時或結束時的有效狀態,而不是某個事務執行一半的中間狀態。
  4. 持久性 (Durability)

    • 含義:一旦事務成功提交,其對數據庫數據的改變就是永久性的,即使系統發生故障(如電源中斷、系統崩潰),這些改變也不會丟失。
    • 例子:銀行轉賬成功并提交后,即使銀行系統立即崩潰,轉賬記錄依然存在,不會丟失。通常通過寫入日志文件(redo log)和數據文件來保證。

實踐建議

  • 理解ACID特性是正確設計和實現數據庫業務邏輯的基礎。
  • 在Java應用中,通常通過Spring的 @Transactional 注解或手動管理事務來確保ACID特性,特別是A, C, D。隔離性則通過數據庫的隔離級別和應用層的鎖機制來保證。

7: 事務的隔離級別有哪些?每種隔離級別解決了哪些并發問題?

重點講解

事務的隔離級別定義了多個并發事務同時訪問相同數據時,一個事務對另一個事務可見的程度,以及可能產生的并發問題。ANSI/ISO SQL標準定義了四種隔離級別。

并發問題

  1. 臟讀 (Dirty Read):一個事務讀取了另一個事務尚未提交的數據。如果后者回滾,則前者讀取的數據是無效的。
  2. 不可重復讀 (Non-Repeatable Read):一個事務在不同時間讀取同一數據,但兩次讀取的結果有所不同,因為另一個已提交的事務修改了該數據。
  3. 幻讀 (Phantom Read):一個事務在不同時間查詢同一范圍的數據,但兩次查詢結果的行數不同,因為另一個已提交的事務插入或刪除了該范圍內的行。

四種隔離級別

  1. READ UNCOMMITTED (讀未提交)

    • 特點:最低隔離級別。允許讀取其他事務尚未提交的數據。
    • 解決問題:無(所有并發問題都可能發生)。
    • 可能發生:臟讀、不可重復讀、幻讀。
    • 性能:最高。
    • 適用場景:極少在生產環境使用,因為數據一致性極差。
  2. READ COMMITTED (讀已提交)

    • 特點:只能讀取其他事務已提交的數據。
    • 解決問題:解決了臟讀問題。
    • 可能發生:不可重復讀、幻讀。
    • 性能:較高。
    • 適用場景:大多數數據庫(如Oracle、SQL Server的默認隔離級別)的默認選擇,但在MySQL中不是。可以接受事務內多次查詢結果不一致的場景。
  3. REPEATABLE READ (可重復讀)

    • 特點:保證在一個事務中,多次讀取同一數據(包括范圍查詢),結果始終一致。它通過**MVCC(多版本并發控制)**實現。
    • 解決問題:解決了臟讀不可重復讀問題。
    • 可能發生幻讀(在嚴格意義的標準中仍可能,但在MySQL的InnoDB引擎中,通過Next-Key Locks也解決了幻讀)。
    • 性能:中等。
    • 適用場景MySQL InnoDB 存儲引擎的默認隔離級別。適用于對數據一致性要求較高,且能接受并發插入/刪除操作導致幻讀的場景(如果不是InnoDB的Next-Key Lock)。對于InnoDB,此級別已足夠安全。
  4. SERIALIZABLE (串行化)

    • 特點:最高隔離級別。所有事務都像串行執行一樣,徹底避免所有并發問題。通常通過對讀寫操作加鎖來實現。
    • 解決問題:解決了臟讀不可重復讀幻讀所有并發問題。
    • 可能發生:無。
    • 性能:最低(并發性最差),因為可能導致大量的超時和鎖競爭。
    • 適用場景:對數據一致性要求極高,且并發量極低的場景。極少在生產環境中使用。

MySQL InnoDB 對幻讀的解決
REPEATABLE READ 隔離級別下,InnoDB通過間隙鎖 (Gap Locks)Next-Key Locks(記錄鎖+間隙鎖的組合)來防止幻讀的發生。當事務執行范圍查詢時,不僅鎖定存在的記錄,還會鎖定記錄之間的“間隙”,防止其他事務在此間隙插入新數據。

實踐建議

  • 理解默認級別:了解你使用的數據庫引擎的默認隔離級別(MySQL InnoDB是REPEATABLE READ)。
  • 根據需求選擇:大多數Web應用使用 READ COMMITTEDREPEATABLE READ 就足夠。READ UNCOMMITTEDSERIALIZABLE 應謹慎使用。
  • Spring Boot/Cloud 默認:Java應用通過Spring管理事務時,默認隔離級別通常取決于數據庫,但也可以在 @Transactional 中顯式指定。

8: MySQL 存儲引擎 InnoDB 和 MyISAM 的主要區別是什么?它們各自的適用場景是什么?

重點講解

MySQL 擁有多種存儲引擎,最常用的是 InnoDB 和 MyISAM。它們在特性、性能和適用場景上存在顯著差異。

特性InnoDBMyISAM
事務支持支持 (ACID)不支持
行級鎖支持,提高了并發性能不支持,只有表級鎖
外鍵支持支持,維護參照完整性不支持
B樹索引聚集索引 (數據即索引),輔助索引存主鍵非聚集索引 (索引和數據文件分離)
全文本搜索MySQL 5.6+ 支持早有支持
表崩潰恢復支持 (通過 redo/undo log)不支持,容易損壞,恢復困難
MVCC支持 (多版本并發控制)不支持
緩沖池緩存數據和索引,大量內存使用只有索引緩存,數據依賴OS緩存
表空間既可以存放在共享表空間,也可以獨立文件存儲每張表存儲在獨立的 .MYD (數據) 和 .MYI (索引) 文件
計數(COUNT(*) )需要全表掃描有一個計數器,SELECT COUNT(*) 效率高

適用場景

  1. InnoDB (推薦)

    • 適用場景
      • 絕大多數OLTP (聯機事務處理) 應用:需要事務支持、高并發讀寫、數據完整性(外鍵)。
      • 對數據一致性、完整性有嚴格要求的業務,如電商訂單、金融交易、在線支付等。
      • 需要災難恢復能力、支持行級鎖以提高并發的場景。
    • 總結:默認且首選的存儲引擎,適用于需要高并發、事務和數據安全性的場景。
  2. MyISAM

    • 適用場景
      • 讀密集型應用:表很少有寫操作,并且以查找和瀏覽為主。
      • 對事務、數據完整性要求不高,例如日志表、非關鍵應用的統計數據表。
      • 一些早期或特殊場景的全文本搜索。
      • SELECT COUNT(*) 性能至關重要的場景。
    • 總結:在現代應用中已基本被淘汰,由于不支持事務和行級鎖,并發性能差,恢復性差。僅在極少數特殊讀密集型場景(如早期CMS應用的流量統計)還可能被考慮。

實踐建議

  • 默認使用 InnoDB:除非有非常明確的理由和考量,否則都應該選擇 InnoDB。
  • 在Java Web應用開發中,幾乎總是使用 InnoDB。Spring事務管理、JPA/Hibernate等都嚴重依賴事務特性。

9: SQL 注入是什么?如何防止 SQL 注入攻擊?

重點講解

SQL 注入 (SQL Injection)

  • 定義:SQL 注入是一種代碼注入技術,攻擊者通過在Web表單或URL參數中輸入惡意的SQL命令,欺騙數據庫服務器執行非預期的操作。
  • 危害
    • 繞過身份驗證,以管理員身份登錄系統。
    • 竊取、修改或刪除數據庫中的敏感數據。
    • 獲取數據庫結構信息。
    • 執行系統命令(在某些配置下),完全控制服務器。

攻擊原理
當應用程序將用戶輸入直接拼接成SQL語句,并且沒有對輸入進行適當驗證和轉義時,攻擊者可以通過構造特殊的輸入字符串改變原始SQL語句的執行邏輯

例如,原始SQL:SELECT * FROM users WHERE username = 'admin' AND password = 'password';
攻擊者輸入 username = ' OR 1=1 --
拼接后:SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = 'password';
其中 -- 是SQL注釋符,' AND password = 'password' 被注釋掉,OR 1=1 永遠為真,導致無需密碼即可登錄。

如何防止 SQL 注入攻擊

  1. 使用預編譯語句 (Prepared Statements) 和參數化查詢 (Parameterized Queries)(首選且最重要)

    • 原理:預編譯語句將SQL語句的結構與用戶輸入的數據分開。數據庫會先編譯SQL語句的骨架,然后將用戶輸入作為參數傳入,而不是作為SQL代碼的一部分進行解析。這樣,無論用戶輸入什么,都會被視為普通數據值,而不會影響SQL語句本身的結構。
    • 實現
      • JDBCPreparedStatement
      • ORM框架 (如 Hibernate, MyBatis):它們內部通常就是使用預編譯語句,或提供了參數化的API。
    • 示例 (JDBC)
      String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
      try (PreparedStatement stmt = connection.prepareStatement(sql)) {stmt.setString(1, username);stmt.setString(2, password);try (ResultSet rs = stmt.executeQuery()) {// ... 處理結果}
      }
      
  2. 嚴格的用戶輸入驗證和過濾

    • 原理:在接收用戶輸入時,對數據的類型、長度、格式、內容進行嚴格的檢查。只允許合法字符,禁止特殊字符。
    • 實現
      • 白名單驗證:只允許預期的數據格式(如數字、字母,不允許特殊符號)。
      • 黑名單過濾(不推薦作為唯一手段):過濾掉常見的SQL關鍵字和特殊字符(如 ', --, ;, OR, AND 等),但黑名單容易被繞過。
    • 注意:這是一種輔助手段,不能替代預編譯語句。
  3. 最小權限原則 (Least Privilege)

    • 原理:數據庫用戶應該只擁有執行其任務所必需的最小權限。不要使用 root 或具有 ALL PRIVILEGES 的用戶賬戶連接應用程序。
    • 實現:為應用創建獨立的數據庫用戶,并只授予 SELECT, INSERT, UPDATE, DELETE 等所需權限,禁止 DROP TABLE, GRANT 等高危權限。
  4. 錯誤信息隱藏

    • 原理:不要在生產環境中顯示詳細的數據庫錯誤信息給用戶。攻擊者可以利用這些信息來推斷數據庫的結構和漏洞。
    • 實現:捕獲異常,顯示通用的錯誤消息,并將詳細錯誤記錄在日志文件中。

實踐建議

  • SQL注入是后端安全最常見的也是最危險的漏洞之一PreparedStatement 是防止其最有效和最直接的方法,必須時刻牢記并使用
  • 結合輸入驗證、最小權限原則和錯誤信息隱藏,構建多層次的防御體系。

10: 什么是數據庫范式 (Normal Forms)?請簡述 1NF, 2NF, 3NF 的概念和目的。

重點講解

定義:數據庫范式是關系型數據庫設計的一組規則,旨在減少數據冗余,消除異常數據,并確保數據完整性。主要有第一范式(1NF)、第二范式(2NF)、第三范式(3NF)等。

目的

  • 減少數據冗余:避免相同數據在多處存儲,節省空間。
  • 消除更新異常:在更新數據時,只需更新一處。
  • 消除插入異常:無需插入不相關的數據即可插入某條數據。
  • 消除刪除異常:刪除一條數據不會意外刪除其他相關數據。
  • 提高數據完整性:通過規范化,使得數據保持一致和準確。
  1. 第一范式 (1NF - First Normal Form)

    • 概念:要求數據庫表中的所有列都是原子性的,即不可再分。每個列都不能包含復合值或多值。
    • 目的:確保每個字段的值都是單一的、不可分割的最小單元。
    • 示例 (不符合1NF)
      OrderIDItemDetails
      1“Pen:10, Paper:20”
    • 示例 (符合1NF)
      OrderIDItemNameQuantity
      1Pen10
      1Paper20
  2. 第二范式 (2NF - Second Normal Form)

    • 概念
      1. 先滿足1NF
      2. 非主鍵列必須完全依賴于整個主鍵,而不是主鍵的某個部分。
    • 目的:消除部分函數依賴,進一步減少冗余。通常當主鍵是復合主鍵時才需要考慮2NF。
    • 示例 (不符合2NF)
      OrderDetails (OrderID, ProductID, ProductName, Quantity)
      • 復合主鍵:(OrderID, ProductID)
      • ProductName 依賴于 ProductID (主鍵的一部分),而不是整個復合主鍵。這就是部分函數依賴。
    • 示例 (符合2NF):拆分成兩個表
      Orders (OrderID, ...)
      OrderItems (OrderID, ProductID, Quantity)
      Products (ProductID, ProductName, ...)
  3. 第三范式 (3NF - Third Normal Form)

    • 概念
      1. 先滿足2NF
      2. 非主鍵列之間不存在傳遞函數依賴。也就是說,非主鍵列不能依賴于另一個非主鍵列。
    • 目的:消除傳遞函數依賴,徹底消除冗余。
    • 示例 (不符合3NF)
      Employees (EmployeeID, EmployeeName, DepartmentID, DepartmentName)
      • 主鍵:EmployeeID
      • DepartmentName 依賴于 DepartmentID,而 DepartmentID 又依賴于 EmployeeID
        -> EmployeeID -> DepartmentID -> DepartmentName (傳遞依賴)
    • 示例 (符合3NF):拆分成兩個表
      Employees (EmployeeID, EmployeeName, DepartmentID)
      Departments (DepartmentID, DepartmentName)

反范式化 (Denormalization)
雖然范式化是數據庫設計的重要原則,但在實際應用中,為了提高查詢性能,有時會刻意違反范式規則,進行反范式化。例如,在訂單表中冗余存儲商品名稱,以避免查詢時頻繁 JOIN 商品表。這通常是“以空間換時間”的優化策略,但會增加數據一致性的維護成本。

實踐建議

  • 在設計數據庫時,通常建議至少滿足 3NF
  • 理解范式有助于設計出清晰、高效、易于維護的數據庫結構。
  • 過度范式化(如BNCF或更高級范式)可能導致表過多,JOIN 操作頻繁,反而降低查詢性能。實際工作中,通常在滿足3NF的基礎上,根據業務需求和性能瓶頸考慮適當的反范式化。
  • 在Java應用中,ORM框架(如Hibernate)會自動處理多表關聯,減輕了部分范式化帶來的復雜性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/94447.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/94447.shtml
英文地址,請注明出處:http://en.pswp.cn/web/94447.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PostgreSQL診斷系列(2/6):鎖問題排查全攻略——揪出“阻塞元兇”

🔗 接上一篇《PostgreSQL全方位體檢指南》,今天我們深入數據庫的“神經系統”——鎖機制,解決最令人頭疼的“卡頓”問題。 你是否經歷過: 某個SQL執行著就不動了?應用界面卡在“加載中”?UPDATE 語句遲遲不…

crc16是什么算法

核心概念?CRC16? 是一種循環冗余校驗算法,屬于哈希函數的一種。它的核心目的是檢測數據的錯誤,通常用于數字網絡和存儲設備中,來驗證數據在傳輸或存儲后是否依然完整、無誤。你可以把它想象成一個數據的“指紋”或“摘要”。發送方計算出一…

Day8--HOT100--160. 相交鏈表,206. 反轉鏈表,234. 回文鏈表,876. 鏈表的中間結點

Day8–HOT100–160. 相交鏈表,206. 反轉鏈表,234. 回文鏈表,876. 鏈表的中間結點 每日刷題系列。今天的題目是力扣HOT100題單。 鏈表題目。 160. 相交鏈表 思路【我】: 1,計算鏈表長度 2,令A為較短鏈&am…

Rust面試題及詳細答案120道(58-65)-- 集合類型

《前后端面試題》專欄集合了前后端各個知識模塊的面試題,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs&…

Horse3D游戲引擎研發筆記(八):在QtOpenGL環境下,按需加載彩虹四邊形的頂點屬性 (Unity、Unreal Engine、Three.js與Godot)

在上一篇博客中,我們探討了如何在QtOpenGL環境下使用改進的Uniform變量管理方式繪制多彩四邊形。本文將延續這一主題,深入探討如何在QtOpenGL環境下按需加載彩虹四邊形的頂點屬性。這一功能是Horse3D引擎渲染系統的重要組成部分,旨在實現靈活…

模塊化設計+微米級精度,GelSight Modulus 觸覺型3D輪廓儀深入檢測“盲區”

當航空航天工程師在精密艙體中搜尋微米級缺陷,汽車檢查員在車間復雜結構里排查隱患,能源領域創新者嘗試突破檢測邊界時,深耕視觸覺 3D 顯微技術的企業——GelSight,正以全新研發的GelSight Modulus觸覺型3D輪廓儀(簡稱…

Pytorch安裝詳細步驟

第一步:檢查顯卡支持的的CUDA版本 1.打開NVIDIA控制面板 首先鼠標右擊桌面-顯示更多選項-NVIDIA控制面板-點擊彈出界面右上角的(系統信息)-點擊彈出界面的(組件) 2.查看驅動版本 打開系統信息 點擊組件,查看 以觀測到紅色方框內的信息可以看到(NVIDIA CUDA 13.0.…

2025職場進階:低門檻技能實用手冊

每到年初,都會有人問:如果只能投入有限的時間與預算,先考哪一兩本證書更劃算?本文把近兩年的崗位需求、學習可獲得性與花費周期做了綜合權衡,給出一個以“先提升通用能力,再疊加行業資質”為主線的組合方案…

SDC命令詳解:使用set_timing_derate命令進行約束

相關閱讀 SDC命令詳解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目錄 指定降額比例 指定降額對象列表/集合 指定沿 指定最大、最小條件 指定早、晚條件 指定路徑的類型 指定降額類型 指定約束 指定增量 寫在最后 由于制造…

C++語言程序設計——03 進制ASCII碼

目錄一、進制表示與轉換(一)不同進制表示(二)進制轉換方法二、ASCII 碼(一)ASCII 碼表(二)ASCII 碼轉換(三)大小寫英文字母轉換【總結:如何記憶AS…

AtCoder Beginner Contest 420-Toggle Maze

題目描述 有一個 H行 W 列的網格。用 (i,j) 表示位于第 i 行(從上往下數)第 j 列(從左往右數)的格子。每個格子的狀態用字符 Ai,j表示,含義如下: . :空格子。 #’ :障礙格子。 S &am…

20、DMA----釋放CPU壓力,加快傳輸

1、DMA介紹DMA,全稱為:Direct Memory Access,即直接存儲器訪問。DMA傳輸方式無需CPU直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場的過程,通過硬件為RAM與I/O設備開辟一條直接傳送數據的通路,能使…

深入OpenHarmony OTA硬核升級

技術背景 OpenHarmony OTA(Over-The-Air)升級子系統為設備提供了遠程升級能力,通過統一的升級接口屏蔽底層芯片差異,支持輕量系統、小型系統和標準系統的全量升級、差分升級和變分區升級。 核心特性 跨系統支持:覆蓋輕量系統(Hi3861)、小型系統(Hi3516DV300)、標準系…

華為iVS1800接入SVMSPro平臺

華為iVS1800接入SVMSPro平臺 ** 華為好望Huawei HolosensIVS1800智能視頻云平臺采用首款昇騰310加持的嵌入式系統智能微邊緣,獨俱普惠AI鴻力。一臺融合存儲、計算、檢索功能,滿足小型園區、社區、銀行網點、超市等場景安防需求,小機大智。 …

《異形戰機2》v2.0.4數字豪華版,3D橫版射擊再臨,機體武器海量升級

[游戲名稱]: 《異形戰機2》v2.0.4數字豪華版 [軟件大小]: 17.7 GB [軟件大小]: 夸克網盤 | 百度網盤 游戲介紹 《異形戰機:最終版2》續作震撼登場!經典橫版射擊全面升級:3D 畫面炫目、關卡與機體海量擴充,只為帶來酣暢淋漓的滅…

Java 異常(Throwable)

1. Throwable Throwable: 所有異常和錯誤的根類。實現 Throwable 或其子類的對象才能被 throw 或 catch。 Error: 表示嚴重的系統級問題,通常不應該被捕獲或處理,程序通常無法從中恢復。 Exception: 表示程序可以處理的問題。分為 運行時異常、 受檢異常…

rocketmq常用命令

官方文檔 https://rocketmq.apache.org/zh/docs/ https://rocketmq.apache.org/zh/docs/domainModel/02topic/ https://rocketmq.apache.org/zh/docs/4.x/deployment/02admintool 集群配置管理 https://mp.weixin.qq.com/s/688wNSwZPraGvAnr0K7hRw RocketMQ運維管理命令mqadm…

【C++詳解】哈希表概念與實現 開放定址法和鏈地址法、處理哈希沖突、哈希函數介紹

文章目錄一、unordered系列的使用unordered_set類的介紹unordered_set和set的使?差異unordered_map和map的使?差異unordered_xxx的哈希相關接?二、哈希表實現哈希概念直接定址法哈希沖突負載因?將關鍵字轉為整數哈希函數除法散列法/除留余數法乘法散列法處理哈希沖突開放定…

電影感人文街拍擺攤紀實攝影后期Lr調色教程,手機濾鏡PS+Lightroom預設下載!

調色介紹電影感人文街拍擺攤紀實攝影后期 Lr 調色是一種專注于捕捉街頭生活煙火氣的攝影風格,通過 Lightroom 后期調色賦予畫面電影般的敘事感和情感深度。這種風格以擺攤小販、市井行人、街頭場景為主體,強調真實、自然的生活瞬間。調色核心在于低飽和暖…

【數據分享】298個地級市人工智能企業數量(1990-2023)

數據介紹引言人工智能產業作為數字經濟的核心驅動力,其發展規模與分布格局深刻反映區域科技創新活力與產業升級潛力。為助力相關研究,本文分享一份涵蓋全國 298 個地級市 1990-2023 年的人工智能企業核心數據,包含人工智能企業存量和人工智能…