菜鳥的mysql進階

說明

一直想學習一下mysql進階的相關知識,剛好趁着前段時間redis學完,可以學習一下mysql的進階,簡單瞭解了一下進階的相關知識,還挺多的,感覺之前的mysql學的好像只是簡單入門而已。本文會持續更新,不斷地擴充

本文僅爲記錄學習軌跡,如有侵權,聯繫刪除

一、mysql的存儲引擎

引擎
MySQL中的數據用各種不同的技術存儲在文件(或者內存)中。這些技術中的每一種技術都使用不同的存儲機制、索引技巧、鎖定水平並且最終提供廣泛的不同的功能和能力。通過選擇不同的技術,你能夠獲得額外的速度或者功能,從而改善你的應用的整體功能。

查看mysql支持的存儲引擎
命令show engines;
在這裏插入圖片描述
我這邊的mysql版本是8.0以上的,可以看到mysql支持的存儲引擎還不少,它默認的存儲引擎是InnoDB,當然,這個跟我的mysql的配置文件有關
在這裏插入圖片描述
我這邊設置了默認的引擎和字符串,所以不同配置的mysql可能跟我這個有些不同。

MyISAM與InnoDB區別
這裏重點提出來學習一下這個兩個引擎,因爲這兩個好像是最常見的兩個。

MyISAM InnoDB
文件構成 每個MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義。數據文件的擴展名爲.MYD (MYData)。 索引文件的擴展名是.MYI (MYIndex)。 基於磁盤的資源是InnoDB表空間數據文件和它的日誌文件,InnoDB 表的大小隻受限於操作系統文件的大小,一般爲 2GB
事務 不提供事務支持 InnoDB提供事務支持事務
執行速度 MyISAM類型的表強調的是性能,其執行數度比InnoDB類型更快 InnoDB相較速度慢了一點
CURD操作 如果執行大量的SELECT,MyISAM是更好的選擇 如果你的數據執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表
外鍵 不支持外鍵 支持外鍵
主鍵 允許沒有主鍵的表存在。 如果沒有設定主鍵,就會自動生成一個 6 字節的主鍵(用戶不可見)。
MyISAM 只支持表級鎖 InnoDB 支持行級鎖和表級鎖,默認是行級鎖,行鎖大幅度提高了多用戶併發操作的性能。
全文索引 MyISAM 支持全文索引。 InnoDB 不支持全文索引 ,但innodb 從 mysql5.6 版本開始提供對全文索引的支持。

經過本人查詢之後,發現它們之間的區別還不止這些,這些只是相對比較重要的區別。

MyISAM與InnoDB選擇
關於這兩種存儲引擎的選擇,網上有很多說法,我個人比較認可的是要根據需求和存儲引擎來決定。比如像一些簡單的需求,沒有複雜的數據表的關係,數據大多以查詢和插入爲主,並且對安全性沒有特別高的要求,這個時候就建議用MyISAM引擎,如果是涉及到的表有很多,而且各種表還有一些複雜的關聯,平時除了查詢之外,更新數據也挺頻繁的,更重要的是安全性要求特別高,這個時候出於各種綜合考慮,建議用InnoDB引擎,因爲該引擎支持事務等高級操作。

總之,對於存儲引擎的選擇,需要結合各種引擎的特點以及需求來進行選擇。

二、事務的ACID原則

這裏給大家推薦篇兩篇博客,這一部分的內容都是基於這兩篇博客的整合
博客一博客二

什麼是ACID

ACID 說明
原子性(Atomicity) 原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
一致性(Consistency) 事務前後數據的完整性必須保持一致。
隔離性(Isolation) 事務的隔離性是多個用戶併發訪問數據庫時,數據庫爲每一個用戶開啓的事務,不能被其他事務的操作數據所幹擾,多個併發事務之間要相互隔離。
持久性(Durability) 持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響

有一個非常經典的銀行轉賬的例子就可以很好的體現了這4個原則。銀行轉賬主要分兩個步驟,假設有A和B賬戶,A賬戶現有800元,B賬戶現有200元
在這裏插入圖片描述
轉賬過程:A減200元,B加200元兩個步驟要麼都成功,要麼都失敗,不會出現A減200後,B卻不加200的情況,這就是原子性,轉賬前A加B總額1000元,轉賬後也是1000元,這就是一致性,如果有多個用戶併發的在執行轉賬,那麼它們之前的事務應該是互補干擾的,這就是隔離性,事務執行成功後,即轉賬成功後,數據就被持久化到數據庫了,這就是持久性

髒讀、不可重複讀和幻讀
在進行web系統的開發的時候,有一個必須要考慮的重點,那就是併發處理,雖然自己平時學校裏面的一些實訓很少會做併發的處理,但是學到現在,自己會有意識的考慮併發的一些情況。額,扯遠了,就是說在高併發的情況,可能會出現髒讀、不可重複讀和幻讀的情況,下面給出相應的概述。

  • 髒讀
    所謂髒讀,就是指事務A讀到了事務B還沒有提交的數據,比如銀行取錢,事務A開啓事務,此時切換到事務B,事務B開啓事務–>取走100元,此時切換回事務A,事務A讀取的肯定是數據庫裏面的原始數據,因爲事務B取走了100塊錢,並沒有提交,數據庫裏面的賬務餘額肯定還是原始餘額,這就是髒讀。

  • 不可重複讀
    所謂不可重複讀,就是指在一個事務裏面讀取了兩次某個數據,讀出來的數據不一致。還是以銀行取錢爲例,事務A開啓事務–>查出銀行卡餘額爲1000元,此時切換到事務B事務B開啓事務–>事務B取走100元–>提交,數據庫裏面餘額變爲900元,此時切換回事務A,事務A再查一次查出賬戶餘額爲900元,這樣對事務A而言,在同一個事務內兩次讀取賬戶餘額數據不一致,這就是不可重複讀。

  • 幻讀
    所謂幻讀,就是指在一個事務裏面的操作中發現了未被操作的數據。比如學生信息,事務A開啓事務–>修改所有學生當天簽到狀況爲false,此時切換到事務B,事務B開啓事務–>事務B插入了一條學生數據,此時切換回事務A,事務A提交的時候發現了一條自己沒有修改過的數據,這就是幻讀,就好像發生了幻覺一樣。幻讀出現的前提是併發的事務中有事務發生了插入、刪除操作。

事務隔離級別
其實在應對上面的併發問題,我第一個想到的是用鎖。。。,爲了應對上面的出現的併發問題,就有了事務隔離級別,因爲事務隔離級別越高,在併發下會產生的問題就越少,但同時付出的性能消耗也將越大,因此很多時候必須在併發性和性能之間做一個權衡。
事務隔離級別有4種,但是像Spring會提供給用戶5種

事務隔離級別 說明
DEFAULT 默認隔離級別,每種數據庫支持的事務隔離級別不一樣,如果Spring配置事務時將isolation設置爲這個值的話,那麼將使用底層數據庫的默認事務隔離級別。順便說一句,如果使用的MySQL,可以使用"select @@tx_isolation"來查看默認的事務隔離級別
READ_UNCOMMITTED 讀未提交,即能夠讀取到沒有被提交的數據,所以很明顯這個級別的隔離機制無法解決髒讀、不可重複讀、幻讀中的任何一種,因此很少使用
READ_COMMITED 讀已提交,即能夠讀到那些已經提交的數據,自然能夠防止髒讀,但是無法限制不可重複讀和幻讀
REPEATABLE_READ 重複讀取,即在數據讀出來之後加鎖,類似"select * from XXX for update",明確數據讀取出來就是爲了更新用的,所以要加一把鎖,防止別人修改它。REPEATABLE_READ的意思也類似,讀取了一條數據,這個事務不結束,別的事務就不可以改這條記錄,這樣就解決了髒讀、不可重複讀的問題,但是幻讀的問題還是無法解決
SERLALIZABLE 串行化,最高的事務隔離級別,不管多少事務,挨個運行完一個事務的所有子事務之後纔可以執行另外一個事務裏面的所有子事務,這樣就解決了髒讀、不可重複讀和幻讀的問題了

給出網上整理的圖
在這裏插入圖片描述

級別越高效率越低,一般情況下會設置爲READ_COMMITED,此時避免了髒讀,併發性也還不錯,之後再通過一些別的手段去解決不可重複讀和幻讀的問題就好了。

三、數據庫設計的三大範式

關於數據庫設計的三大範式,首推這篇博客

第一範式(1NF)
要求數據庫表的每一列都是不可分割的原子數據項。
例子:
在這裏插入圖片描述
像這種情況是不行的,因爲家庭信息和學校信息的數據是可以再分的,比如家庭地址,家裏人口數等,是屬於可分割的原子數據項,所以上面這張表是不符合第一範式的,最好的做法是再拆分出家庭信息表和學校信息表

第二範式(2NF)
在滿足第一範式的前提下,非碼屬性必須完全依賴於候選碼(在1NF基礎上消除非主屬性對主碼的部分函數依賴),第二範式需要確保數據庫表中的每一列都和主鍵相關,而不能只與主鍵的某一部分相關(主要針對聯合主鍵而言)。

一句話總結就是,一張表只能存放對應的一件事情
例子
在這裏插入圖片描述
很明顯,這種設計是不符合第二範式的,單從字段上看就知道,這張表描述了兩件事情,產品和訂單,所以,這種設計違反了第二範式。

第三範式(3NF)
在滿足第一和第二範式的前提下,任何非主屬性不依賴於其它非主屬性(在2NF基礎上消除傳遞依賴),第三範式需要確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。

一句話總結就是,表的每一個字段都應該直接與主鍵相關,間接相關是不行的
例子
在這裏插入圖片描述
很明顯,後面班主任相關的字段好像跟主鍵學號不是直接相關的,而像是間接相關的,所以這也是不符合第三範式的,應該通過外鍵,將班主任與學生關聯起來,兩張表相關聯。

規範與性能
既然三大範式是規範的話,那數據庫設計是不是都要符合三大範式纔行呢,顯然不是的,說到規範就必須要說到性能了,很多情況下,規範和項目的性能往往不能兼得,爲了規範化,得犧牲一部分性能,尤其是在海量數據的情況下,所以,在規範和性能之間要做一個權衡。

不過就個人而已,我會優先考慮性能,然後再考慮規範化,我寧願查詢的性能高一點,哪怕是不符合三大範式,最常見的就是給表增加一些冗餘字段,將多表查詢變爲單表查詢,雖然可能不符合三大範式,但在大量數據的情況下,這能提高效率。

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