一)垂直分庫
什麼是垂直切分?通俗的講就是將我們的數據庫按照模塊劃分成不同的數據庫,以此來解決數據庫訪問的壓力。例如,下面的案例將會把原始包含訂單,用戶,商品,倉配等信息的數據庫劃分爲訂單庫,用戶庫,商品庫三個數據庫。但實際訪問還是相當於訪問一個數據庫一樣,這裏就需要藉助我們的MyCat來配置邏輯數據庫了
如果是在實際線上,若是爲了保證在作垂直分庫的時候不受影響,前一步我們需要完成各個節點的主從同步工作,這樣之後做了分庫,切換訪問mycat,才能保證數據不會錯亂。關於mysql的主從同步可以詳細看【Mysql 主從複製實戰】
1)首先看一下我們的環境
所以在演示如何具體的劃分之前,需要按照上面的準備好我們演示環境
2)因爲我們這次只是演示數據庫的垂直分庫,所以只是涉及到了MyCat的【schema.xml】和【server.xml】,並不會用到【rule.xml】,所以這裏指出可以將關注重點放在【schema.xml】和【server.xml】兩個文件上面
3)創建我們連接mycat的用戶並授權,在我們配置【schema.xml】的時候需要用到
create user mycat@'192.168.124.%' identified by '123456';
grant select,insert,update,delete on *.* to mycat@'192.168.124.%';
4)下面就是配置我們的【schema.xml】
上面是我們原始數據庫的所有表,現在要做一個垂直的拆分,按照我們上面所說需要分成三個庫,下面看我們的詳細配置
打開【shcema.xml】,下面是詳細的配置
<schema name="mycat_db" checkSQLschema="false" sqlMaxLimit="100">
<table name="order_master" primarykey="order_id" dataNode="orderDB" />
<table name="order_detail" primarykey="order_detail_id" dataNode="orderDB" />
<table name="order_cart" primarykey="cart_id" dataNode="orderDB" />
<table name="order_customer_addr" primarykey="customer_addr_id" dataNode="orderDB" />
<table name="region_info" primarykey="region_id" dataNode="orderDB" />
<table name="shipping_info" primarykey="ship_id" dataNode="orderDB" />
<table name="warehouse_info" primarykey="w_id" dataNode="orderDB" />
<table name="warehouse_proudct" primarykey="wp_id" dataNode="orderDB" />
<table name="product_brand_info" primarykey="brand_id" dataNode="productDB" />
<table name="product_category" primarykey="category_id" dataNode="productDB" />
<table name="product_comment" primarykey="comment_id" dataNode="productDB" />
<table name="product_info" primarykey="product_id" dataNode="productDB" />
<table name="product_supplier_info" primarykey="supplier_id" dataNode="productDB" />
<table name="product_pic_info" primarykey="product_pic_id" dataNode="productDB" />
<table name="customer_balance_log" primarykey="balance_id" dataNode="customerDB" />
<table name="customer_inf" primarykey="customer_inf_id" dataNode="customerDB" />
<table name="customer_level_inf" primarykey="customer_level" dataNode="customerDB" />
<table name="customer_login" primarykey="customer_id" dataNode="customerDB" />
<table name="customer_login_log" primarykey="login_id" dataNode="customerDB" />
<table name="customer_point_log" primarykey="point_id" dataNode="customerDB" />
</schema>
<dataNode name="orderDB" dataHost="mysql39" database="order_db" />
<dataNode name="productDB" dataHost="mysql40" database="product_db" />
<dataNode name="customerDB" dataHost="mysql41" database="customer_db" />
<dataHost name="mysql39" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="192.168.124.39" url="192.168.124.39:3306" user="mycat" password="123456"/>
</dataHost>
<dataHost name="mysql40" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="192.168.124.40" url="192.168.124.40:3306" user="mycat" password="123456"/>
</dataHost>
<dataHost name="mysql41" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="192.168.124.41" url="192.168.124.41:3306" user="mycat" password="123456"/>
</dataHost>
5)配置我們的【server.xml】
<system>
<property name="serverPort">8066</property>
<property name="managerPort">9066</property>
<property name="nonePasswordLogin">0</property>
<property name="bindIp">0.0.0.0</property>
<property name="frontWriteQueueSize">2048</property>
<property name="charset">utf-8</property>
<property name="txIsolation">2</property>
<property name="processors">8</property>
<property name="idleTimeout">300000</property>
<property name="sqlExecuteTimeout">300</property>
<property name="useSqlStat">0</property>
<property name="useGlobleTableCheck">0</property>
<property name="defaultMaxLimit">100</property>
<property name="maxPacketSize">104857600</property>
</system>
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">mycat_db</property>
</user>
接下來我們便可以使用【root】用戶去登陸mycat了,這裏注意:
<property name="schemas">mycat_db</property> 的mycat_db 一定要和我們【schema.xml】中的schema頭 name的名字一致
6)在我們任意一個數據庫節點登陸進行驗證
我們使用【mysql_node4】去驗證
mysql -uroot -p123456 -P8066 -h192.168.124.38
登陸成功,然後看一下我們的數據庫,只有我們配置的一個邏輯數據庫【mycat_db】,查看一下表,顯示了原始數據庫的所有表,具體如下圖:
至此我們的mycat垂直分庫基本配置完畢。
7)簡單總結一下垂直分庫的優缺點
優點:
1)數據庫的拆分簡單明瞭,拆分規則明確
2)應用程序模塊清晰明確,整合容易
3)數據維護方便,容易定位
缺點:
1)部分表關聯無法在數據庫級別完成,需要在程序中完成
2)對於訪問極其頻繁且數據量超大的表任然存在性能瓶頸
3)切分達到一定程度之後,擴展性會遇到限制
二)冗餘數據清理
上面做分庫之前都是做了主從同步的,所以雖然我們現在將原始數據庫做了拆分,但是拆分之後還是有數據冗餘的,現在每一份數據庫都保留着最原始的所有數據庫表,所以現在我們需要做一下刪除冗餘數據的處理
具體操作其實也很簡單,
1)首先停止掉我們之前所有節點的主從同步機制
stop slave;
2)然後將對應模塊的數據庫中無用的表做一個刪除處理,這裏我直接使用客戶端手動去刪除就可以了。清理之後如下圖:
三個數據庫只是保留各自模塊的表
3)驗證
再次登陸我們的mycat
mysql -uroot -p123456 -P8066 -h192.168.124.38
查看對應的表
show tables;
還是我們配置的所有邏輯表,冗餘數據刪除成功
三)全局表的配置使用
爲何要使用全局表?當我們在做兩個模塊的聯合查詢的時候,因爲現在做了分庫,無法通過關聯的sql語句做查詢,通常我們的解決方案會有以下三種:
1)使用Mycat的全局表
2)相關表中做冗餘數據
3)使用API的方式獲取數據
鑑於講解mycat的使用,這裏簡單說一下mycat的全局表的配置
基本思路:
1)三個數據庫中需要各自保持一份表數據
2)修改我們【schema.xml】的邏輯表的全局配置
這裏我們使用節點2中 【region_info】表來做演示,這是一個省市的數據表
1)導出數據表
mysqldump -uroot -p order_db region_info > region_info;
2)分別將導出的表數據拷貝到節點3(192.168.124.40)和節點4(192.168.124.41)中
scp region_info [email protected]:/root
scp region_info [email protected]:/root
3)然後分別導入到各個數據庫中
mysql -uroot -p product_db < region_info
mysql -uroot -p customer_db < region_info
4)修改我們【schema.xml】中的配置
<table name="region_info" primaryKey="region_id" dataNode="orderDB,productDB,customerDB" type="global"/>
5)再次啓動我們的mycat
mycat start
再次關聯查詢數據就可以查到了。配置了全局表之後,我們的mycat就會來維護這個全局表的數據。
如何驗證?
通過客戶端連接mycat,修改全局表的數據,分別查看各個節點全局表數據有沒有發生變化,變化了即表示全局表配置成功。