MySQL 學習筆記(Schema、事物)

MySQL 學習筆記(Schema、事物)

Schema 設計

良好的邏輯設計和物理設計是高性能的基石。

數據類型的選擇

  • 更小的通常
  • 更好簡單就好
  • 儘量避免 Null

整數

  • 整數類型: TINYINT 、 SMALLINT 、 MEDIUMINT 、 INT 、 BIGINT;分別使用 8、16、24、32、64 位存儲空間。存儲的範圍從 -2(N-1) 到 2(N-1)-1。
  • 整數類型有可選的 UNSIGNED,表示不允許負值。
  • 有符號和無符號類型使用相同的存儲空間,並具有相同的性能,因此可以根據實際情況選擇合適的類型。
  • MySQL 可以爲整數類型指定寬度,例如 INT(11),這實際沒有意義:它不會限制值的合法範圍。對於存儲和計算來說, INT(1) 和 INT(20) 是相同的。

實數

  • DECIMAL 類型用於存儲精確的小數。CPU 不支持對 DECIMAL 的直接計算。
  • CPU 直接支持原生浮點計算,所以浮點運算明顯更快。
  • MySQL 5.0 和更高版本中的 DECIMAL 類型運行最多 65 個數字。

字符串類型

  • VARCHAR:用於存儲可變長字符串,比定長類型更節省空間
  • CHAR:定長,根據定義分配足夠的空間

使用枚舉(ENUM)代替字符串:

  • 枚舉列可以把一些不重複的字符串存儲成一個預定義的集合。MySQL 在存儲枚舉時非常緊湊,會根據列表值的數量壓縮到一個或者兩個字節中。

BLOB和TEXT 類型

  • BLOB 和 TEXT 都是爲存儲很大的數據而設計的字符串數據類型,分別採用二進制和字符串方式存儲。

日期和時間類型

  • DATETIME: 保存大範圍的值,從 1001 年到 9999 年,精度爲秒。把日期和時間封裝到格式爲 YYYYMMDDHHMMSS 的整數中,與時區無關。使用 8 個字節的存儲空間。
  • TIMESTAMP: 保存從 1970 年 1 月 1 日午夜以來的秒數,和 UNIX 時間戳相同。TIMESTAMP 只使用 4 個字節的存儲空間,範圍是從 1970 年到 2038 年。

MySQL Schema 設計中的陷阱

  • 太多的列
  • 太多的關聯
  • 全能的枚舉
  • 變相的枚舉
  • 非此發明的 NULL

範式和反範式

  • 第一範式(1NF)

符合1NF的關係中的每個屬性都不可再分。1NF是所有關係型數據庫的最基本要求。

  • 第一範式(2NF)

在1NF的基礎上,非主鍵列完全依賴於主鍵,而不能是依賴於主鍵的一部分。

  • 第一範式(3NF)

3NF就是要消除傳遞依賴,方便理解,可以看做是“消除冗餘”。

範式化通常帶來的好處

  • 範式化的更新操作通常比反範式化要快。
  • 當數據較好地範式化時,就只有很少或者沒有重複數據,所以只需要修改更少的數據。
  • 範式化的表通常更小,可以更好地存放在內存裏,所以執行操作會更快。
  • 很少有多餘的數據意味着檢索列表數據時,更少需要 DISTINCT 或者 GROUP BY 語句。
  • 範式化設計的 Schema 的缺點是通常需要關聯。

反範式的優缺點

  • 反範式化的 Schema 因爲所有數據都在一張表中,可以很好地避免關聯。
  • 單獨的表也能使用更有效的索引策略。

事務

事務是一組原子性的 SQL 查詢,或者說是一個獨立的工作單元。事務內的所有操作要麼全部執行成功,要麼全部執行失敗。

四個基本特性

  • Atomicity(原子性):事務是一個不可分割的整體,事務內所有操作要麼全部提交成功,要麼全部失敗回滾。
  • Consistency(一致性):事務執行前後,數據從一個狀態到另一個狀態必須是一致的(A向B轉賬,不能出現A扣了錢,B卻沒收到)。
  • Isolation(隔離性):多個併發事務之間相互隔離,不能互相干擾。或者說一個事務所做的修改在最終提交以前,對其他事務是不可見的。
  • Durablity(持久性):事務完成後,對數據庫的更改是永久保存的,不能回滾。

事務隔離級別

Read Uncommitted(未提交讀)

在 Read Uncommitted 級別,事務中的修改,即使沒有提交,對其他事務也都是可見的。事務可以讀取未提交的數據,這也被稱爲髒讀(Dirty Read)。性能不會好太多,但是問題卻一大堆,實際應用中一般很少使用。

Read Committed(提交讀)

大多數數據庫系統的默認隔離級別都是 Read Committed。Read Committed 滿足前面提到的隔離性的簡單定義:一個事務開始時,只能“看見”已經提交的事務所做的修改。換句話說:一個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的。有時也叫不可重複讀(Nonrepeatable Read)。

Repeatable Read(可重複讀)

Repeatable Read 解決了髒讀的問題。但是還是無法解決領一個幻讀(Phantom Read)問題。所謂幻讀,指的是當某個事務在讀取某個範圍內的記錄時,另外一個事務又在該範圍內插入了新的記錄,當之前的事務再次讀取該範圍的記錄時,會產生幻行(Phantom Row)。InnoDB 和 XtraDB 存儲引擎通過多版本併發控制(MVCC,Multiversion Concurrency Control)解決了幻讀的問題。

Repeatable Read(可重複讀)在讀的過程中數據始終是事務啓動時的數據狀態,未提交之前其他事物的增刪改操作提交後都不會影響讀的結果。讀的是快照結果。

Serializable(可串行化)

Serializable 是最高的隔離級別。它通過強制事務串行執行,避免了前面說的幻讀問題。簡單來說,Serializable 會在讀取的每一行數據上都加鎖,所以導致大量的超時和鎖爭用的問題。實際中,極少使用。

注意:Repeatable Read(可重複讀) 是 MySQL 默認事務隔離級別

引擎

MySQL存儲引擎MyISAM與InnoDB區別

存儲引擎Storage engine:MySQL中的數據、索引以及其他對象是如何存儲的,是一套文件系統的實現。

常用的存儲引擎有以下:

  • Innodb引擎:Innodb引擎提供了對數據庫ACID事務的支持。並且還提供了行級鎖和外鍵的約束。它的設計的目標就是處理大數據容量的數據庫系統。
  • MyIASM引擎(原本Mysql的默認引擎):不提供事務的支持,也不支持行級鎖和外鍵。
  • MEMORY引擎:所有的數據都在內存中,數據的處理速度快,但是安全性不高。

死鎖

死鎖是指兩個或者多個事務再同一資源上相互佔用,並請求鎖定對方佔用的資源,從而導致惡性循環的現象。當多個事務試圖以不同的順序鎖定資源時,就可能會產生死鎖。多個事務同事鎖定相同的資源時,也會產生死鎖。

InnoDB 目前處理死鎖的方法是,將持有最少行級排他鎖的事務進行回滾。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章