標籤:
一、Mysql分表的原因
1、當一張的資料達到幾百萬時,你查詢一次所花的時間會變多,如果有聯集查詢的話,我想有可能會死在那兒了。
分表的目的就在於此,減小資料庫的負擔,縮短查詢時間。2、mysql中有一種機制是表鎖定和行鎖定,為什麼要出現這種機制,是為了保證資料的完整性,我舉個例子來說吧,如果有二個sql都要修改同一張表的同一條資料,這個時候怎麼辦呢,是不是二個sql都可以同時修改這條資料呢?很顯然mysql對這種情況的處理是,一種是表鎖定(myisam儲存引擎),一個是行鎖定(innodb儲存引擎)。表鎖定表示你們都不能對這張表進行操作,必須等我對錶操作完才行。行鎖定也一樣,別的sql必須等我對這條資料操作完了,才能對這條資料進行操作。如果資料太多,一次執行的時間太長,等待的時間就越長,這也是我們為什麼要分表的原因。
二、分表的規則
這裡只討論最簡單的分表規則模數
假如我們需要把使用者表分為100張表
user進行水平的切分,產生兩個表結構完全一樣的user_1,user_2等表,user_1 + user_2 + …的資料剛好是一份完整的資料。
1)我們採用最簡單的分表方案 模數我們根據使用者的id來模100比如 使用者id為1000156 模上100 為56 那添加資料或者讀取資料的時候 都是在user_56這個表操作 下面是分表的指令碼
#!/bin/sh # dev | idcdbenv=dev if [ "${dbenv}" = "dev" ]; then mysql_user=root mysql_pass=root mysql_host=fiif [ "${dbenv}" = "idc" ]; then mysql_user=root mysql_pass=root mysql_host="-h 10.10.10.10"fi mysql_cmd="mysql -u${mysql_user} -p${mysql_pass} ${mysql_host} --default-character-set=utf8" for i in {1..100}do ${mysql_cmd} <<EOF use md_mydatabasel; create table t_user_$i ( f_uin bigint(20) NOT NULL DEFAULT ‘0‘, f_name varchar(256) NOT NULL DEFAULT ‘‘, PRIMARY KEY (f_uin) )ENGINE=InnoDB DEFAULT CHARSET=utf8; EOF done
下面是刪除表的指令碼
#!/bin/sh # dev | idcdbenv=dev if [ "${dbenv}" = "dev" ]; then mysql_user=root mysql_pass=root mysql_host=fiif [ "${dbenv}" = "idc" ]; then mysql_user=midea mysql_pass=MD_midea mysql_host="-h 10.10.10.10"fi mysql_cmd="mysql -u${mysql_user} -p${mysql_pass} ${mysql_host} --default-character-set=utf8" for i in {1..100}do ${mysql_cmd} <<EOF use md_mydatabasel; drop table t_user_$i; EOFdone
2)每張表需要保證 使用者的id為全域唯一的有個簡單的解決方案是 在資料庫裡面 建立一個表 只有一個欄位 是專門用來取號碼的即每次 需要建立一個新使用者,則從這個表裡面取一個號碼 同時讓這個號碼增加一個這個來保證每個使用者的id都是全域唯一的
CREATE TABLE t_global_number ( f_global_id bigint(20) NOT NULL, PRIMARY KEY (f_global_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8
3)關於資料讀取我們盡量讓請求不要直接去查詢資料庫我們可以每次查到資料就放到redis的緩衝裡面。如果資料沒改變則一直用緩衝一旦資料改變了就 刪除緩衝這樣可以減輕資料庫的查詢負擔
三、分庫分表產生的問題,及注意事項
1. 分庫分表維度問題
假如使用者購買了商品,需要將交易記錄儲存取來,如果按照使用者的緯度分表,則每個使用者的交易記錄都儲存在同一表中,所以很快很方便的尋找到某使用者的購買情況,但是某商品被購買的情況則很有可能分布在多張表中,尋找起來比較麻煩。反之,按照商品維度分表,可以很方便的尋找到此商品的購買情況,但要尋找到買人的交易記錄比較麻煩。
所以常見的解決方式有:
a.通過掃表的方式解決,此方法基本不可能,效率太低了。
b.記錄兩份資料,一份按照使用者緯度分表,一份按照商品維度分表。
c.通過搜尋引擎解決,但如果即時性要求很高,又得關係到即時搜尋。
2. 聯集查詢的問題
聯集查詢基本不可能,因為關聯的表有可能不在同一資料庫中。
3. 避免跨庫事務
避免在一個事務中修改db0中的表的時候同時修改db1中的表,一個是操作起來更複雜,效率也會有一定影響。
4. 盡量把同一組資料放到同一DB伺服器上
例如將賣家a的商品和交易資訊都放到db0中,當db1掛了的時候,賣家a相關的東西可以正常使用。也就是說避免資料庫中的資料依賴另一資料庫中的資料。
一、mysql分表簡單介紹