轉(zhuǎn)至:https://network.51cto.com/art/202110/687283.htm
?
MySQL分表之后,怎么平滑上線?
項(xiàng)目開(kāi)發(fā)中,我們的數(shù)據(jù)庫(kù)數(shù)據(jù)越來(lái)越大,隨之而來(lái)的是單個(gè)表中數(shù)據(jù)太多。以至于查詢數(shù)據(jù)變慢,而且由于表的鎖機(jī)制導(dǎo)致應(yīng)用操作也受到嚴(yán)重影響,出現(xiàn)了數(shù)據(jù)庫(kù)性能瓶頸。
作者:飯米粒?來(lái)源:??程序員小飯??|2021-10-26 09:27
???收藏??
????分享??
????
分表的目的
項(xiàng)目開(kāi)發(fā)中,我們的數(shù)據(jù)庫(kù)數(shù)據(jù)越來(lái)越大,隨之而來(lái)的是單個(gè)表中數(shù)據(jù)太多。以至于查詢數(shù)據(jù)變慢,而且由于表的鎖機(jī)制導(dǎo)致應(yīng)用操作也受到嚴(yán)重影響,出現(xiàn)了數(shù)據(jù)庫(kù)性能瓶頸。
當(dāng)出現(xiàn)這種情況時(shí),我們可以考慮分表,即將單個(gè)數(shù)據(jù)庫(kù)表進(jìn)行拆分,拆分成多個(gè)數(shù)據(jù)表,然后用戶訪問(wèn)的時(shí)候,根據(jù)一定的算法,讓用戶訪問(wèn)不同的表,這樣數(shù)據(jù)分散到多個(gè)數(shù)據(jù)表中,減少了單個(gè)數(shù)據(jù)表的訪問(wèn)壓力。提升了數(shù)據(jù)庫(kù)訪問(wèn)性能。
舉個(gè)栗子
比如咱們最常見(jiàn)的用戶表(user表)
id | user_id | 其他字段 |
主鍵id | 用戶id | 其他字段 |
咱們一般都會(huì)用user_id去查詢對(duì)應(yīng)的用戶信息,但是隨著業(yè)務(wù)的增長(zhǎng),這張表會(huì)越來(lái)越大,甚至上億,嚴(yán)重影響了查詢性能。所以咱們就會(huì)對(duì)這張表進(jìn)行分表處理,分到多張表減小查詢壓力。
分表策略
以分10張表為例(具體分多少?gòu)埍恚鶕?jù)實(shí)際情況來(lái)估算) 首先咱們建10張表 user1、user2、user3。。。。。user10。
一般情況下,我們都會(huì)用作為索引的字段(user_id)進(jìn)行取模處理。想分多少?gòu)埍?,就按照多少取模,比如這個(gè)case就是10。
1. $table_name = $user_id % 10;
按照上面的取模公式:
- user_id為1295的會(huì)落在user5里面
- user_id為8634的會(huì)落在user4里面
- 。。。。。。。
「每次CURD根據(jù)上面查找表的策略進(jìn)行就行了」,這個(gè)問(wèn)題不大,我們暫且先不多說(shuō)。
已經(jīng)上線的運(yùn)行中的表怎么辦?
其實(shí)上面的方法大家應(yīng)該都知道怎么用,但是有個(gè)問(wèn)題,已經(jīng)上線了的表怎么辦?那張表的數(shù)據(jù)在線上是一直被查找或者改變的。如何能夠進(jìn)行平滑的分表,并且讓用戶無(wú)感知呢?
方法1
直接上線,提前寫(xiě)個(gè)腳本,腳本內(nèi)容是把舊表(user)的數(shù)據(jù)同步到user1表到user10表,一上線了趕緊執(zhí)行
這種方法明顯是行不通的,主要是存在以下問(wèn)題:
如果執(zhí)行過(guò)程中腳本有問(wèn)題怎么辦?代碼全部回滾?
腳本把把舊表(user)的數(shù)據(jù)同步到user1表到user10表,這個(gè)腳本得執(zhí)行多久?如果是1個(gè)小時(shí),那么這段時(shí)間線上和這張表相關(guān)的業(yè)務(wù)都是不正常的
這顯然是行不通的,對(duì)線上影響很大。
方法2
先寫(xiě)個(gè)同步數(shù)據(jù)的腳本,腳本內(nèi)容是把舊表(user)的數(shù)據(jù)同步到user1表到user10表,腳本同步完了再上線。
這個(gè)方法看起來(lái)友好了一些,不過(guò)也存在一些問(wèn)題。
腳本同步完,立即上線,這兩件事之間是有一些時(shí)間差的,這個(gè)時(shí)間差中線上表可能有一些改動(dòng),這些改動(dòng)怎么辦?
「以上兩種方法看起來(lái)貌似都行不通,所以看來(lái)得來(lái)點(diǎn)不一樣的了。咱們直接看結(jié)論。」
步驟1 上線雙寫(xiě)
首先咱們把雙寫(xiě)上線了,什么意思呢?比如user_id=123,對(duì)于增加,刪除,修改操作來(lái)說(shuō),咱們既操作user表,也操作user_id=123對(duì)應(yīng)的user3表。
1. function modify($user_id){ //包含增加,刪除,修改操作
2. modify_user(); //modify user表
3. $table_name = $user_id % 10;
4. modify_user($table_name) //modify對(duì)應(yīng)的分表
5. }
因?yàn)椴樵兊牟糠诌€是在user表中查詢的,所以上面的操作對(duì)線上用戶是無(wú)任何影響的。
步驟2 全量同步
寫(xiě)一個(gè)全量同步user表到user1-user10的表,最好找個(gè)低峰期執(zhí)行腳本,以防萬(wàn)一影響user表的查詢
這一步執(zhí)行之后,因?yàn)樵蹅冎吧暇€了雙寫(xiě)(見(jiàn)步驟1),所以u(píng)ser表和user1-user10表之間的數(shù)據(jù)已經(jīng)是完全一致的了。
步驟3 查詢新表數(shù)據(jù)
將查詢的部分改到user1-user10
因?yàn)榍懊鎯蓚€(gè)步驟咱們已經(jīng)保證了user表和各個(gè)分表之間的數(shù)據(jù)完全一致性,所以直接把查詢的部分改掉是沒(méi)有任何問(wèn)題的。
如果按照以上步驟執(zhí)行,那么對(duì)線上的數(shù)據(jù)是沒(méi)有任何影響的,而且我們線上就是這么操作了,經(jīng)過(guò)了多次實(shí)踐確保不會(huì)出問(wèn)題,放心使用即可。
本文摘自 :https://blog.51cto.com/s