mysql相關梳理

mysql是如何實現事務的
數據庫事務性的確保:ACID機制

  • 原子性(A):undo(回滾日誌)
  • 一致性(C):
  • 隔離性(I):四個隔離級別(InnoDB默認使用可重複讀)
  • 持久性(D):通過redo(重做日誌)

讀寫分離何時強制要讀主庫,讀哪個從庫是通過什麼方式決定的,從庫的同步mysql用的什麼方式

  • 讀寫在同一事務,或者讀取數據要求無延遲,則一定要讀主庫;
  • 從庫與主庫間通過binlog 同步

問:如何優化mysql的查詢?

  • 優化mysql查詢緩存,提升命中率(如使用變量替代函數)
  • 通過EXPLAIN查看分析處理流程,找出性能瓶頸並優化
  • 優化索引
  • 儘可能使用not null(NULL仍然需要額外空間,並且在比較時程序會更復雜)
  • 對大數據表做拆分(垂直、水平)
  • 考慮使用本地緩存+mysql優化熱點數據查詢
  • 對一些特殊的特點數據,可以先離線統計出來放入前置緩存查詢,避免查詢瓶頸(如買家庫中的大賣家)

問:mysql的索引主要有哪幾種?

  • 主要有B+樹索引和哈希索引等

索引在數據庫中有什麼作用?

  • 加快數據查詢(減少掃描數據量、避免服務器的排序和臨時表、將隨機IO轉爲順序IO)
  • 索引是對數據表中一或多個列進行排序的結構。與搜索所有行相比,索引用指針指向存儲(在表中指定列)的數據,然後根據指定次序排列這些指針,有助於更快獲取信息。索引將佔用磁盤空間,影響數據更新速度,但多數情況下索引帶來的速度優勢大大超過不足。
  • 主鍵、二級索引、覆蓋索引

使用索引時的注意點

  • 索引會大大提高檢索速率,但也降低更新速率,因爲需要額外更新索引
  • 索引不會包含有NULL的列(數據庫設計時不要讓字段默認值爲NULL)
  • 索引要精短(節省存儲,提升效率),對於長的索引字段可使用前綴截取
  • like操作不推薦,使用的話,"%aaa%"不會使用索引,"aaa%"可以使用索引(最左前綴)
  • 多列索引時,要將選擇性最高的列放最前面,但需要排序操作時排序字段一般最優先索引

問題:使用索引一定能提升性能嗎?

  • 索引需要存儲空間,所以也不是越多越好,如果引入索引的成本比不用索引增加的成本更大,就最好不用索引
  • 如果數據表中數據少,沒有必要創建索引
  • 修改的性能明顯多於檢索時,建議少創建索引,因爲索引會增加修改的成本

問:B+樹索引和哈希索引有何優劣?

  • B+樹索引是innoDB引擎默認的索引方式,檢索和更新複雜度爲O(logN)(與樹的高度相關),可以支持範圍查詢

  • 哈希索引基於哈希表,只支持單值的查詢更新,但是效率很高,複雜度爲O(1),適合特定離散的熱點數據做索引,innoDB引擎實現了自適應哈希索引,如果發現特定數據滿足熱點數據條件就自動爲其創建哈希索引

  • 爲什麼默認使用B+樹實現索引?
    索引往往以文件形式存儲在磁盤,索引查找就要產生磁盤I/O,評價索引優劣最重要指標就是查找過程磁盤I/O次數。
    B-Tree中一次檢索最多需要h-1次I/O(根節點常駐內存),漸進複雜度爲O(logmN)。一般m非常大,因此h非常小(通常不超過3)。
    綜上,用B-Tree作爲索引結構效率非常高。

問:B+樹的結構有什麼特點?

  • (1)每個父節點元素都會出現在子節點中,且爲子節點的最大或最小元素
  • (2)葉子節點包含所有的數據元素的關聯信息,其他節點僅爲索引,沒有數據關聯
  • (3)每個葉子節點都有指針指向下一節點,形成一個有序鏈表。

問:Mysql的聚集索引和非聚集索引有何區別?

  • 聚集索引是按表中主鍵改構造的一個B+樹,每張表只有一個聚集索引(對應一個主鍵),索引葉子節點即爲對應的數據節點,因此InnoDB表數據文件本身就是聚集索引。聚集索引對於按主鍵的排序和範圍查找非常快。
  • 非聚集索引即輔助索引,一個表可以有多個,通過該索引查找時先遍歷索引通過葉指針獲得指向聚集索引的主鍵,然後通過聚集索引查找完整數據(兩次檢索)。
  • 爲什麼不建議使用過長字段做主鍵?
    因爲所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。
  • 爲什麼經常使用自增字段做主鍵?
    因爲InnoDB數據文件本身是一顆B+Tree,非單調主鍵會造成插入新記錄時數據文件爲維持B+Tree特性而頻繁分裂調整,十分低效,而使用自增字段作主鍵則是好選擇。

爲什麼非聚集索引要存儲指向聚集索引的主鍵,而不是直接存儲節點的物理地址?(這樣可以少一次指針查詢)

  • 是由B+樹的索引結構決定的,B+樹在插入數據時會出現頁分裂,如果在中間位置分裂,而後面所有節點的物理地址都會改變,這樣直接存物理地址的更新成本是無法接受的。

問:Mysql在併發事務中可能產生哪些問題?

  • (1)髒讀:事務A讀取到了B的更新數據,如果B回滾的話,A讀到的成爲髒數據
  • (2)不可重複讀:事務B在A多次讀取同一數據時對該數據做更新提交導致A讀取的數據前後不一致(側重於修改)
  • (3)幻讀:類似不可重複讀,不過是在過程中對數據做了增或刪。

問:Mysql的事務隔離層級有哪幾種?可以解決以上哪些併發問題?

  • (1)讀未提交:3個都沒解決
  • (2)讀已提交(RC級別):解決髒讀問題
  • (3)可重複讀(RR級別,InnoDB默認):解決髒讀和不可重複讀問題
  • (4)串行化:解決全部問題,但性能差
  • InnoDB默認使用層級(3),並通過優化策略解決了幻讀問題

問:InnoDB通過什麼策略解決了幻讀問題,同時又保證性能?

  • Mysql的MVCC保證高併發性能,使用next-key lock解決幻讀問題
  • 對於簡單讀(簡單select),不用加鎖(讀取記錄的快照版本)
  • 對於當前讀(增刪改,這些操作需要先獲取最近版本數據,然後進一步操作),需要加鎖-(next-key lock)(讀取記錄的最新版本)

問:InnoDB在當前讀時是如何加鎖的?

  • 如果表中只有一個聚集索引,那麼只會對直接命中的行加鎖
  • 如果表中同時存在非聚集索引,需要加GAP鎖,確保在多次讀取之間其他事物不會插入新的滿足條件的記錄並提交。

問:InnoDB引擎有哪些關鍵特性?

  • (1)插入緩衝(Insert Buffer):在非聚集索引插入或更新時,不直接插入到索引ye ,而是先判斷索引頁是否在緩衝池,在的話直接插入,不在則放入一個Inset Buffer對象;然後再以一定頻率進行Buffer和索引頁節點的merge。這樣大大提升了非聚集索引插入更新的性能。

  • (2)雙寫(提高數據可靠性)由doubleWriter buffer和磁盤共享空間組成,做髒頁刷新時先寫buffer然後同步共享空間(連續存儲,效率高),之後再將buffer數據寫到表文件。如果寫表過程中崩潰,引擎先從共享空間中找到該頁的副本,複製到表空間文件,然後使用重做日誌恢復數據。

  • 問:爲什麼不直接使用重做日誌恢復數據?

  • 答:因爲重做日誌記錄的是頁的物理操作,如果頁本身損壞是無法重做的,因此重做之前需要一個頁的副本做基準。

  • (3)自適應哈希索引:監控索引頁查詢,如果發現建立哈希索引可以提升性能,即創建之(自動創建)。

  • (4)異步IO:提升磁盤操作性能,可以支持IO的merge。

  • (5)刷新臨接頁:刷新髒頁時,同時判斷該頁所在區所有頁,如果爲髒頁一併刷新。

問: mysql中的binlog、redo log、undo log有何區別?

  • binlog:是MySQL Server層記錄的日誌,是邏輯日誌,不支持併發,用於數據恢復、主從複製等
  • redo log(重做日誌):InnoDB引擎記錄的日誌,是物理日誌(速度比邏輯日誌快很多,所以InnoDB優先使用redo log而不是binlog),支持併發,作用同binlog,用來保證事務的原子性和持久性。包含重做日誌緩衝和重做日誌文件(異步刷寫)
  • undo log:爲實現事務一致性的日誌,數據操作前先備份數據到undo log,如果事務執行中出錯或rollback,可使用log中的備份將數據恢復到原有狀態。

問:怎麼通過binlog完成數據恢復?

  • 先通過mysqlbinlog命令恢復binlog日誌並導入文件
  • 然後通過source命令導入數據表中

mysql如何完成主從同步

  • 通過binlog追趕

  • 精衛中間件:解析binlog,轉爲MQ消息發給備庫,備庫消費消息完成同步,消息中間件提供消息有序性的保證(可靠可重試,異步鬆耦合,擴展性好,吞吐量大)

>>InnoDB的一致性讀是怎麼實現的?需要加鎖嗎?

  • 默認情況下使用一致性非鎖定讀,不加鎖
  • 一些情況下可以在讀取時顯式加鎖以保證邏輯一致性 select … for update

>>如何解決多併發導致的死鎖問題?

  • (1)爲每個事務設置超時時間,超時自動回滾某個或某些事務;(2)執行死鎖檢測(狀態圖),檢測到死鎖後回滾某些事務以消除循環依賴(一般回滾undo鏈路短的事務–回滾成本低)

什麼是聚集索引?有哪些好處?又有哪些潛在的問題
把數據行和索引(主鍵)緊湊存儲在一起,一個數據表文件其實就是一個聚集索引

好處

  • 通過主鍵的精準和範圍查詢效率很高

問題

  • 插入性能依賴於插入順序,因此要求主鍵爲順序遞增
  • 更新聚集索引的代價高,會強制將每個被更新的行移動到新位置
  • 插入新行可能導致頁分裂問題(主鍵不連續的話)
  • 可能造成二級索引比想象中大,因爲二級索引葉子需要包含主鍵(要求主鍵字段儘可能短小)
  • 造成二級索引查詢需要兩次索引查找(查詢主鍵值+查詢主鍵對應的行)

如何避免二級索引的第二次索引查找—使用覆蓋索引

如何使用索引排序–讓索引的次序和order by子句順序完全一致,並且所有列的排序方向都一致

Mysql的主從同步(複製)有哪幾種方式?

  • 基於語句的複製
  • 基於行的複製

開放題目:分庫分表

常見的分庫分表方式有哪些?

  • 根據業務字段取模分表(需要遷移數據)
  • 一致性哈希分表(支持動態擴展)
  • 雪花算法生成全局ID分表(支持動態擴展)(最高位始終爲0----41位的時間序列,精確到ms,可以根據時間排序----10位機器標識,最多支持部署1024個節點----12位計數序列號(自增id),12位的計數序列號支持每個節點每毫秒產生4096個ID序號。)

一致性哈希的原理是什麼?

  • 把節點對應哈希值變成一個範圍而不再是離散的,如果有節點加入會從原來某個節點分管一部分範圍的哈希值。
  • 新增一個節點,只有一個其他節點會受影響—問題:造成負載不均衡
  • 改進:引入虛擬節點,一個物理節點對應多個虛擬節點,可以均勻插入哈希環中。這樣增減物理節點相對會增減很多虛擬節點,確保負載相對均衡。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章