共計 3089 個字符,預計需要花費 8 分鐘才能閱讀完成。
本篇內容介紹了“MySQL 怎么使用分庫分表”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
MySQL 使用分庫分表
1 什么是分庫分表?
把原本存儲于一個庫的數據分塊存儲到多個庫上,把原本存儲于一個表的數據分塊存儲到多個表上。
2 為什么要分庫分表?
數據庫中的數據量不一定是可控的,在未進行分庫分表的情況下,隨著時間和業務的發展,庫中的表會越來越多,表中的數據量也會越來越大,相應地,數據操作,增刪改查的開銷也會越來越大;另外,由于無法進行分布式式部署,而一臺服務器的資源(CPU、磁盤、內存、IO 等)是有限的,最終數據庫所能承載的數據量、數據處理能力都將遭遇瓶頸。
3 分庫分表的實施策略。
分庫分表有垂直切分和水平切分兩種。
3.1 何謂垂直切分,即將表按照功能模塊、關系密切程度劃分出來,部署到不同的庫上。例如,我們會建立定義數據庫 workDB、商品數據庫 payDB、用戶數據庫 userDB、日志數據庫 logDB 等,分別用于存儲項目數據定義表、商品定義表、用戶數據表、日志數據表等。
3.2 何謂水平切分,當一個表中的數據量過大時,我們可以把該表的數據按照某種規則,例如 userID 散列,進行劃分,然后存儲到多個結構相同的表,和不同的庫上。例如,我們的 userDB 中的用戶數據表中,每一個表的數據量都很大,就可以把 userDB 切分為結構相同的多個 userDB:part0DB、part1DB 等,再將 userDB 上的用戶數據表 userTable,切分為很多 userTable:userTable0、userTable1 等,然后將這些表按照一定的規則存儲到多個 userDB 上。
3.3 應該使用哪一種方式來實施數據庫分庫分表,這要看數據庫中數據量的瓶頸所在,并綜合項目的業務類型進行考慮。
如果數據庫是因為表太多而造成海量數據,并且項目的各項業務邏輯劃分清晰、低耦合,那么規則簡單明了、容易實施的垂直切分必是首選。
而如果數據庫中的表并不多,但單表的數據量很大、或數據熱度很高,這種情況之下就應該選擇水平切分,水平切分比垂直切分要復雜一些,它將原本邏輯上屬于一體的數據進行了物理分割,除了在分割時要對分割的粒度做好評估,考慮數據平均和負載平均,后期也將對項目人員及應用程序產生額外的數據管理負擔。
在現實項目中,往往是這兩種情況兼而有之,這就需要做出權衡,甚至既需要垂直切分,又需要水平切分。我們的游戲項目便綜合使用了垂直與水平切分,我們首先對數據庫進行垂直切分,然后,再針對一部分表,通常是用戶數據表,進行水平切分。
4 分庫分表存在的問題。
4.1 事務問題。
在執行分庫分表之后,由于數據存儲到了不同的庫上,數據庫事務管理出現了困難。如果依賴數據庫本身的分布式事務管理功能去執行事務,將付出高昂的性能代價;如果由應用程序去協助控制,形成程序邏輯上的事務,又會造成編程方面的負擔。
4.2 跨庫跨表的 join 問題。
在執行了分庫分表之后,難以避免會將原本邏輯關聯性很強的數據劃分到不同的表、不同的庫上,這時,表的關聯操作將受到限制,我們無法 join 位于不同分庫的表,也無法 join 分表粒度不同的表,結果原本一次查詢能夠完成的業務,可能需要多次查詢才能完成。
4.3 額外的數據管理負擔和數據運算壓力。
額外的數據管理負擔,最顯而易見的就是數據的定位問題和數據的增刪改查的重復執行問題,這些都可以通過應用程序解決,但必然引起額外的邏輯運算,例如,對于一個記錄用戶成績的用戶數據表 userTable,業務要求查出成績最好的 100 位,在進行分表之前,只需一個 order by 語句就可以搞定,但是在進行分表之后,將需要 n 個 order by 語句,分別查出每一個分表的前 100 名用戶數據,然后再對這些數據進行合并計算,才能得出結果。
下面是分庫分表產生的問題,及注意事項
分庫分表維度的問題
假如用戶購買了商品, 需要將交易記錄保存取來,如果按照用戶的緯度分表,則每個用戶的交易記錄都保存在同一表中,所以很快很方便的查找到某用戶的購買情況,但是某商品被購買的情況則很有可能分布在多張表中,查找起來比較麻煩。反之,按照商品維度分表,可以很方便的查找到此商品的購買情況,但要查找到買人的交易記錄比較麻煩。
所以常見的解決方式有:
a. 通過掃表的方式解決,此方法基本不可能,效率太低了。
b. 記錄兩份數據,一份按照用戶緯度分表,一份按照商品維度分表。
c. 通過搜索引擎解決,但如果實時性要求很高,又得關系到實時搜索。
聯合查詢的問題
聯合查詢基本不可能,因為關聯的表有可能不在同一數據庫中。
避免跨庫事務
避免在一個事務中修改 db0 中的表的時候同時修改 db1 中的表,一個是操作起來更復雜,效率也會有一定影響。
盡量把同一組數據放到同一 DB 服務器上
例如將賣家 a 的商品和交易信息都放到 db0 中,當 db1 掛了的時候,賣家 a 相關的東西可以正常使用。也就是說避免數據庫中的數據依賴另一數據庫中的數據。
一主多備
在實際的應用中,絕大部分情況都是讀遠大于寫。Mysql 提供了讀寫分離的機制,所有的寫操作都必須對應到 Master,讀操作可以在 Master 和 Slave 機器上進行,Slave 與 Master 的結構完全一樣,一個 Master 可以有多個 Slave, 甚至 Slave 下還可以掛 Slave, 通過此方式可以有效的提高 DB 集群的 QPS.
所有的寫操作都是先在 Master 上操作,然后同步更新到 Slave 上,所以從 Master 同步到 Slave 機器有一定的延遲,當系統很繁忙的時候,延遲問題會更加嚴重,Slave 機器數量的增加也會使這個問題更加嚴重。
此外,可以看出 Master 是集群的瓶頸,當寫操作過多,會嚴重影響到 Master 的穩定性,如果 Master 掛掉,整個集群都將不能正常工作。
所以,1. 當讀壓力很大的時候,可以考慮添加 Slave 機器的分式解決,但是當 Slave 機器達到一定的數量就得考慮分庫了。2. 當寫壓力很大的時候,就必須得進行分庫操作。
MySQL 使用為什么要分庫分表?
可以用說用到 MySQL 的地方, 只要數據量一大, 馬上就會遇到一個問題, 要分庫分表.
這里引用一個問題為什么要分庫分表呢?MySQL 處理不了大的表嗎?
其實是可以處理的大表的. 我所經歷的項目中單表物理上文件大小在 80G 多, 單表記錄數在 5 億以上, 而且這個表
屬于一個非常核用的表: 朋友關系表.
但這種方式可以說不是一個最佳方式. 因為面臨文件系統如 Ext3 文件系統對大于大文件處理上也有許多問題.
這個層面可以用 xfs 文件系統進行替換. 但 MySQL 單表太大后有一個問題是不好解決: 表結構調整相關的操作基
本不在可能. 所以大項在使用中都會面監著分庫分表的應用.
從 Innodb 本身來講數據文件的 Btree 上只有兩個鎖, 葉子節點鎖和子節點鎖, 可以想而知道, 當發生頁拆分或是添加
新葉時都會造成表里不能寫入數據.
所以分庫分表還就是一個比較好的選擇了.
那么分庫分表多少合適呢?
經測試在單表 1000 萬條記錄一下, 寫入讀取性能是比較好的. 這樣在留點 buffer, 那么單表全是數據字型的保持在
800 萬條記錄以下, 有字符型的單表保持在 500 萬以下.
如果按 100 庫 100 表來規劃, 如用戶業務:
500 萬 100100 = 50000000 萬 = 5000 億記錄.
心里有一個數了, 按業務做規劃還是比較容易的.
“MySQL 怎么使用分庫分表”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注丸趣 TV 網站,丸趣 TV 小編將為大家輸出更多高質量的實用文章!