1. 程式人生 > >MySQL分庫分表方案

MySQL分庫分表方案

人員 有趣的 而不是 其他 代理 延時 分片 -o 得到

  • 1. MySQL分庫分表方案
    • 1.1. 問題:
    • 1.2. 回答:
      • 1.2.1. 最好的切分MySQL的方式就是:除非萬不得已,否則不要去幹它。
      • 1.2.2. 你的SQL語句不再是聲明式的(declarative)
      • 1.2.3. 你招致了大量的網絡延時
      • 1.2.4. 你失去了SQL的許多強大能力
      • 1.2.5. MySQL沒有API保證異步查詢返回順序結果
      • 1.2.6. 總結

MySQL分庫分表方案

翻譯一個stackoverflow上的問答,關於分庫分表的缺點的,原文鏈接:
MySQL sharding approaches?

問題:

什麽是最好的MySQL分庫分表方案?我想到的有:

  1. 應用層切分?
  2. MySQL代理層切分?
  3. 提供查找數據庫分片的中心服務?

你們知道任何這方面有趣的項目或者工具嗎?

回答:

最好的切分MySQL的方式就是:除非萬不得已,否則不要去幹它。

當你寫一個應用時,你通常都想要最快的開發速度。只有必要時,你才開始優化延時,提高吞吐量,

你切分數據庫的原因無非因為數據庫的讀或者寫

  • 數據庫寫
    寫操作永久的超過了服務器的磁盤負載;太多寫入導致副本同步永遠的落後了。
  • 數據庫讀
    讀取到的數據量太大以至於稱爆內存;並且大多數讀操作開始直擊磁盤而不是從內存中讀取數據。

只有這時,你才需要考慮做數據庫切分。

當你開始切分後,你開始以下面幾種方式支付代價:

你的SQL語句不再是聲明式的(declarative)

一般的,你用SQL語句告訴數據庫你要什麽數據,然後讓優化器優化SQL,並將SQL轉化成數據獲取程序。
這很棒,因為它非常靈活,而且寫這些轉化程序很無聊,嚴重影響開發速度。

分布式環境下,你將A節點的表和B節點的表進行join,甚至有些表的數據大到超過一個節點,
在A節點和B節點將數據join起來,然後將B節點和C節點join後的數據再次聚合。
你開始寫單方面的hash應用程序來解決這個問題(或者你可以再造MySQL的集群),
這表示結果你得到一大堆的非聲明式的SQL,而且讓程序以一種面向過程的方式開始工作

你招致了大量的網絡延時

一般的,一條SQL查詢語句可以本地解決並且通過優化器以最小的耗時解決這個查詢問題。

在分布式環境下,查詢語句必須要通過KV映射,訪問多個網絡節點(希望是批量訪問,
而不是每個Key都來一次網絡往返),或者將WHERE條件放在他們將被執行的節點上。

但是即使在最好的情況下,涉及到多個網絡訪問都會更加復雜。特別是MySQL的優化器完全不知道網絡延時的情況。

你失去了SQL的許多強大能力

好吧,這或許沒那麽重要,但是外鍵約束,其他保證數據完整性的SQL機制,對於跨多個節點是無能為力的。

MySQL沒有API保證異步查詢返回順序結果

當相同類型的數據存放在多個節點上(比如用戶數據存放在A,B,C節點上),水平查詢需要訪問所有節點,
數據訪問時間直接因以節點數線性增長。除非多個節點是以並行方式訪問,然後再以Map-Reduce的方式聚合。

前提是需要提供異步通信的API,但這並不存在於MySQL提供的功能中。可選的方案是在子進程中增加很多的forking和連接。

總結

當你開始做數據庫分庫分表,數據結構和網絡拓撲明顯影響到應用的性能。
為了運行良好,你的應用需要當心這些事情,所以只有應用層的切分才有意義。

如果需要自動切分,問題會更多(比如決定那個節點的那個列作為hash主鍵),或者
你想要手動進行切分,xyz用戶去這個主庫上,abc去和def去到那個主庫上。

業務功能上的切分有些好處,如果做對了,這對絕大部分開發人員是透明的。因為所有相關的表都存放在本地。
這讓程序的透明性可以從聲明式的SQL中盡量受益,並且有更少的網絡延時,因為跨節點的網絡訪問被保持到最小化。

業務功能上的切分的缺點是:它不能準許單個表的數據膨脹過大,這需要設計者的特別註意。

業務功能切分的好處是:針對一個並沒有太多改變的代碼庫,它相對而言非常簡單。
Booking.com在過去幾年進行過幾次業務功能上的分庫分表,並且一直工作的很好。

MySQL分庫分表方案