mysql分库分表风险_数据库分库分表存在的问题及解决方案
讀寫分離分散了數(shù)據(jù)庫讀寫操作的壓力,但是沒有分散存儲壓力,當數(shù)據(jù)庫的數(shù)據(jù)量達到千萬甚至上億條的時候,單臺數(shù)據(jù)庫服務器的存儲能力就會達到瓶頸,主要體現(xiàn)在以下幾個方面:
數(shù)據(jù)量太大,讀寫性能會下降,即使有索引,索引也會變得很大,性能同樣會下降
數(shù)據(jù)文件會變得很大,數(shù)據(jù)庫備份和恢復需要消耗更長的時間
數(shù)據(jù)文件越大,極端情況下丟失數(shù)據(jù)的風險就會越高
基于上述原因,單個數(shù)據(jù)庫服務器存儲的數(shù)據(jù)量不能太大,需要控制在一定的范圍內(nèi),為了滿足業(yè)務數(shù)據(jù)存儲的需求,需要將存儲分散到多臺數(shù)據(jù)庫服務器上
常見的分散存儲的方法有分庫和分布兩大類
業(yè)務分庫? 業(yè)務分庫之的是按照業(yè)務模塊將數(shù)據(jù)分散到不同的數(shù)據(jù)庫服務器,雖然業(yè)務分庫能夠分散存儲和訪問的壓力,但是同時也帶來了新的問題,主要存在的問題如下:
join操作問題? ? ?業(yè)務分庫后,原本在同一個數(shù)據(jù)庫中的表分散到不同數(shù)據(jù)庫中,導致無法使用SQL中的join查詢
事務問題? ? ? ? ? ?原本在同一個數(shù)據(jù)庫中不同的表可以在同一個事物中修改,業(yè)務分庫后,表分散到不同的數(shù)據(jù)庫中,無法通過事務統(tǒng)一修改,雖然數(shù)據(jù)庫廠商針對此問題提供了一些分布式事務解決方案(例如,MySQL的XA),但是性能實在太低,與高性功能存儲的目標是相違背的
成本問題? ? ? ? ? 業(yè)務分庫同時也帶來了成本的代價,本來1臺服務器搞定的事情,現(xiàn)在需要3臺,如果考慮備份,那就是2臺變成了6臺
基于上述原因,對于初創(chuàng)業(yè)務,并不建議一開始就這樣拆分,主要有幾個原因:
初創(chuàng)業(yè)務存在很大的不確定性,業(yè)務不一定能發(fā)展起來,業(yè)務開始的時候并沒有真正的存儲和訪問壓力,業(yè)務分庫并不能為業(yè)務帶來價值
業(yè)務分庫后,表之間的join查詢,數(shù)據(jù)庫事務無法簡單實現(xiàn)了發(fā)
業(yè)務分庫后,因為不同的數(shù)據(jù)要讀寫不同的數(shù)據(jù)庫,代碼需要增加根據(jù)數(shù)據(jù)類型映射到不同數(shù)據(jù)庫的邏輯,增加了工作量,而業(yè)務初創(chuàng)期最重要的是快速實現(xiàn),快速驗證,業(yè)務分庫會拖慢業(yè)務節(jié)奏
分表? 將不同的業(yè)務數(shù)據(jù)分散存儲到不同的數(shù)據(jù)庫服務器,能夠支撐百萬甚至千萬用戶規(guī)模的業(yè)務,但是如果業(yè)務繼續(xù)發(fā)展,同一個業(yè)務的單表數(shù)據(jù)也會達到單臺數(shù)據(jù)庫服務器的處理瓶頸,此時就需要對單表進行拆分,單表數(shù)據(jù)拆分有兩種方式:垂直分表和水平分表
分表能夠有效的分散存儲壓力和帶來性能提升,但是和分庫一樣,也會引入各種復雜性,主要存在的問題如下:
垂直分表? 垂直分表適合將表中某些不常用而且占了大量空間的列拆分出去,垂直分表的引入的復雜性主要體現(xiàn)在表操作的數(shù)量會增加,例如原來只要一次查詢的就可以獲取,現(xiàn)在要查詢兩次或者多次才能獲得想要的數(shù)據(jù)
水平分表? 水平分表適合表行數(shù)特別大的表,如果單表行數(shù)超過5000萬就必須進行分表,這個數(shù)字可以作為參考,但是并不是絕對的標準,關鍵還是要看表的訪問性能
水平分表相比垂直分表,會引入更多的復雜性,主要表現(xiàn)在以下幾個方面:
路由? ?水平分表后,某條數(shù)據(jù)具體屬于哪個切分后的表,需要增加路由算法進行計算,這個算法會引入一定的復雜性,常見的路由算法有如下幾種:
范圍路由? ?選擇有序的數(shù)據(jù)列作為路由條件,不同分段分散到不同的數(shù)據(jù)庫表中,以常見的用戶ID為例,路由算法可以按照10000的范圍大小進行分段 1-9999放到數(shù)據(jù)庫1中的表,10000-19999的數(shù)據(jù)放到數(shù)據(jù)庫2中的表,依次類推,范圍路由算法的復雜性主要體現(xiàn)在分段大小的選取上,分段太小會導致切分后的子表數(shù)據(jù)量過多,增加維護復雜度;分段太大可能會導致單表依然存在性能問題,一般建議分段大學在100萬到200萬之間,具體要根據(jù)業(yè)務選擇合適的大小分段,路由算法的優(yōu)點就是可以隨著數(shù)據(jù)的增加可以平滑的擴充新的表,原有的數(shù)據(jù)不需要懂,范圍路由的一個比較隱含的缺點就是分布不均勻
Hahs路由算法? 選擇某個列(或者某幾個列組合也可以)的進行Hash運算,然后根據(jù)Hash結果分散到不同的數(shù)據(jù)庫表中,同樣根據(jù)用戶ID為例,假如一開始就規(guī)劃10個數(shù)據(jù)庫表,路由算法可以簡單的用user_id%10的值來表示數(shù)據(jù)所屬的數(shù)據(jù)庫表編號,ID為985的用戶放到編號為5的子表中,ID為10086的用戶放到編號為6的子表中;Hash 路由算法設計的復雜點主要體現(xiàn)在初始表數(shù)量的選取上,表數(shù)量太多維護比較麻煩,表數(shù)據(jù)量太少又可能導致單表性能問題,而用了Hash路由后,增加表的數(shù)量非常麻煩,所有數(shù)據(jù)都要重新分布,Hash路由算法的優(yōu)缺點和范圍路由基本相反,Hash路由算法的優(yōu)點是表分布比較均勻,缺點是擴充新的表很麻煩,所有數(shù)據(jù)需要重新分布
配置路由? 配置路由就是路由表,用一張獨立的表來記錄路由信息,同樣根據(jù)用戶ID為例,我們新增一張user_router表,這個表包含user_id和table_id兩列,根據(jù)user_id就可以查詢對應的table_id,配置路由設計簡單,使用起來非常靈活,尤其是在擴充表的時候,只需要遷移指定書,然后修改路由表就可以。配置路由的缺點就是必須多查詢一次,會影響整體的性能;而且路由表本身如果太大,性能同樣可能成為瓶頸,如果我們再次將路由表分庫分表,則面臨一個死循環(huán)式的路由算法選擇問題
分表操作和分庫操作一樣,同樣會存在一些問題,主要體現(xiàn)在如下幾個方面:
join操作? ? ? ? ? ?水平分表后,數(shù)據(jù)分散到多個表中,如果需要與其他表進行join 查詢,需要在業(yè)務代碼或者數(shù)據(jù)庫中間件中進行多次join查詢,然后將結果合并
count()操作? ? ?水平分表后,雖然物理上數(shù)據(jù)分散到多個表中,但是某些業(yè)務邏輯上還是會將這些表當作一個表進行處理,例如,獲取記錄總數(shù)用于分頁或展示,水平分表之前用一個count()就能完成的操作,在分表之后就沒有那么簡單了,常見的處理方式有如下兩種:
count()相加? ?具體做法就是在業(yè)務代碼或者數(shù)據(jù)庫中間件中對每個表進行count()操作,然后將結果相加,這種方式實現(xiàn)簡單,缺點就是性能比較低
記錄數(shù)表? ? ? ?具體做法就是新建一張表,例如表名為:記錄數(shù)表,包含table_name,row_count兩個字段,每次插入或刪除子表數(shù)據(jù)成功后,都更新記錄數(shù)表,這種方式獲取表記錄數(shù)的性能要大大優(yōu)于count()相加方式,因為只需要一次簡單的查詢就可以獲得數(shù)據(jù),缺點是復雜度增加不少,對子表的操作要同步操作記錄數(shù)表,如果一個業(yè)務邏輯遺漏了,數(shù)據(jù)就會不一致;而且針對記錄數(shù)表的操作和針對子表的操作無法放在同一個事物中進行處理,異常的情況會出現(xiàn)操作子表成功了而操作記錄數(shù)表示不,同樣導致數(shù)據(jù)不一致,同時,記錄數(shù)表的方式也增加了數(shù)據(jù)庫的寫壓力,因為每次針對子表的insert 和 delete操作需要update記錄數(shù)表,所以對于一些不要去記錄數(shù)實時保持精確的業(yè)務,也可以通過后臺定時更新記錄數(shù)表,定時更新實際上就是count()相加和記錄數(shù)表的結合,定時通過count()相加計算表的記錄數(shù),然后更新記錄數(shù)表中的數(shù)據(jù)
3 order by 操作? ? ?水平分表后,數(shù)據(jù)分散到多個子表中,排序操作無法在數(shù)據(jù)庫中完成,只能由業(yè)務代碼或數(shù)據(jù)庫中間件分表查詢美國子表中的數(shù)據(jù),然后匯總進行排序
總結
以上是生活随笔為你收集整理的mysql分库分表风险_数据库分库分表存在的问题及解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql数据库rpm包_MySQL 8
- 下一篇: 什么数据库比mysql效率高_牛x!一款