場景
比如一個大型集團公司,有一張表record保存了交易記錄信息。該表數據量很大,但是查詢、更新時基本都是按子公司來操作。
那麼可以按子公司編號進行分表。例如子公司編號1的交易記錄存儲到record_1表,同理子公司編號爲2的交易記錄保存到record_2中…
實現
在mysql中新建數據庫實例dbcompany,並新建record0-record3,共4張表,代碼如下
CREATE TABLE `record_0` (
`id` int(11) NOT NULL,
`companyid` int(11) DEFAULT NULL COMMENT '子公司編號',
`info` varchar(255) DEFAULT NULL COMMENT '業務信息',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `record_1` (
`id` int(11) NOT NULL,
`companyid` int(11) DEFAULT NULL COMMENT '子公司編號',
`info` varchar(255) DEFAULT NULL COMMENT '業務信息',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `record_2` (
`id` int(11) NOT NULL,
`companyid` int(11) DEFAULT NULL COMMENT '子公司編號',
`info` varchar(255) DEFAULT NULL COMMENT '業務信息',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `record_3` (
`id` int(11) NOT NULL,
`companyid` int(11) DEFAULT NULL COMMENT '子公司編號',
`info` varchar(255) DEFAULT NULL COMMENT '業務信息',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
配置真實服務器信息
通過修改conf/schema.xml,來配置真實服務器的信息,併爲數據庫劃分節點,指定數據表所在的節點。
注意關鍵信息爲subTables="record_$0-3"
和rule="rule-record"
,通過規則分片後,數據會落入record_0至record_3中。
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- name爲邏輯數據庫名 -->
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<!-- 配置對應表名、子表名、對應數據庫、規則名 -->
<table name="record" subTables="record_$0-3" dataNode="dn1" rule="rule-record" />
</schema>
<!-- 真實數據庫名 -->
<dataNode name="dn1" dataHost="localhost1" database="dbcompany" />
<!-- 配置物理數據庫連接信息 -->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="Easy@0122"/>
</dataHost>
</mycat:schema>
配置路由規則
在schema.xml中我們已經制定了record表存儲的節點,且設置了路由規則的名稱rule-record,然後我們設置該規則具體的策略。
修改conf/role.xml,配置規則如下,注意我們是按companyid列
來進行規則應用的。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
<!-- 規則 -->
<tableRule name="rule-record">
<rule>
<!-- 規則應用的列 -->
<columns>companyid</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- 此處設置有多少個子表即可 -->
<property name="count">4</property>
</function>
</mycat:rule>
配置MyCat服務信息
通過上面兩個配置文件,我們已指定了庫、表、分表路由規則,下面我們將其通過MyCat暴露出來,讓客戶端進行訪問。
通過修改conf/server.xml配置MyCat對外服務信息,主要就是用戶名、密碼、以及上面指定的抽象數據庫名稱TESTDB。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<!-- system部分採用默認即可 -->
<system>
<property name="nonePasswordLogin">0</property> <!-- 0爲需要密碼登陸、1爲不需要密碼登陸 ,默認爲0,設置爲1則需要指定默認賬戶-->
<property name="useHandshakeV10">1</property>
<property name="useSqlStat">0</property> <!-- 1爲開啓實時統計、0爲關閉 -->
<property name="useGlobleTableCheck">0</property> <!-- 1爲開啓全加班一致性檢測、0爲關閉 -->
<property name="sequnceHandlerType">2</property>
<property name="subqueryRelationshipCheck">false</property> <!-- 子查詢中存在關聯查詢的情況下,檢查關聯字段中是否有分片字段 .默認 false -->
<!--默認爲type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool -->
<property name="processorBufferPoolType">0</property>
<!--分佈式事務開關,0爲不過濾分佈式事務,1爲過濾分佈式事務(如果分佈式事務內只涉及全局表,則不過濾),2爲不過濾分佈式事務,但是記錄分佈式事務日誌-->
<property name="handleDistributedTransactions">0</property>
<!--off heap for merge/order/group/limit 1開啓 0關閉-->
<property name="useOffHeapForMerge">1</property>
<!--單位爲m-->
<property name="memoryPageSize">64k</property>
<!--單位爲k-->
<property name="spillsFileBufferSize">1k</property>
<property name="useStreamOutput">0</property>
<!--單位爲m-->
<property name="systemReserveMemorySize">384m</property>
<!--是否採用zookeeper協調切換 -->
<property name="useZKSwitch">false</property>
</system>
<!-- 設置訪問的用戶名密碼 -->
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<!-- 注意此處是之前設定的抽象數據庫名稱 -->
<property name="schemas">TESTDB</property>
</user>
</mycat:server>
啓動測試
雙擊bin/startup_nowrap.bat啓動MyCat,然後使用Navicat或其他工具連接MyCat虛擬的數據庫即可。
我們執行如下8條sql語句
insert into record (id,companyid,info)values(1,1,'test');
insert into record (id,companyid,info)values(4,2,'test');
insert into record (id,companyid,info)values(2,3,'test');
insert into record (id,companyid,info)values(3,4,'test');
insert into record (id,companyid,info)values(5,5,'test');
insert into record (id,companyid,info)values(7,6,'test');
insert into record (id,companyid,info)values(6,7,'test');
insert into record (id,companyid,info)values(8,8,'test');
執行完之後,我們看下真實物理數據庫中的數據:
record_0數據如下,說明是按companyid取模匹配的,我們的策略生效了!
其他三個庫也是按此規則運作的,即數據落入record_[companyid%4]
表。