天天看點

MyCat中對分庫分表、ER表、全局表、分片規則、全局序列等的實作與基本使用操作分庫分表概念實作分庫(垂直)實作分表(水準)ER表的使用全局表的使用常用分片規則全局序列

MyCat的基本使用

  • 分庫分表概念
    • 分庫
    • 分表
  • 實作分庫(垂直)
    • 配置schema檔案
    • 建立資料庫
    • 啟動Mycat
    • 開始分庫
    • 驗證分庫
  • 實作分表(水準)
    • 配置分片規則
    • 配置schma.xml檔案
    • 建立資料庫、表
    • 啟動Mycat
    • 開始分表
    • 驗證分表
  • ER表的使用
    • 配置schema.xml檔案
    • 建立資料庫、表
    • 啟動Mycat
    • 進行查詢
  • 全局表的使用
    • 配置schema.xml檔案
    • 驗證測試
  • 常用分片規則
    • 1.取模
    • 2.範圍約定
    • 3.分片枚舉
    • 4.按日期、天分片
  • 全局序列
    • 全局序列方案
    • 資料庫方式實作全局序列
      • 建庫建表
      • 修改sequence_db_conf.properties配置
      • 修改 server.xml
      • 配置schema.xml檔案
      • 驗證全局序列

分庫分表概念

分庫

分庫又分為:水準分庫與垂直分庫

水準分庫

:把同一個表的資料按一定規則拆到不同的資料庫中

垂直分庫

:按照業務、功能子產品将表進行分類,不同功能子產品對應的表分到不同的庫中

分庫原則

:将緊密關聯關系的表劃分在一個庫裡,沒有關聯關系的表可以分到不同的庫裡

分表

分表又分為:水準分表與垂直分表

水準分表

:在同一個資料庫内,把同一個表的資料按一定規則拆到多個表中

垂直分表

:将一個表按照字段分成多表,每個表存儲其中一部分字段

分表原則

:減少節點資料庫的通路,分表字段尤為重要,其決定了節點資料庫的通路量。

實作分庫(垂直)

配置schema檔案

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
    	
       <!-- 将mytb1、mytb3表分到dn1節點對應MYSQL庫中-->
       <table name="mytb1" primaryKey="id" dataNode="dn1" ></table>
       <table name="mytb3" primaryKey="id" dataNode="dn1" ></table>
       
		<!-- 将mytb2、mytb4表分到dn2節點對應MYSQL庫中-->
        <table name="mytb2" primaryKey="id" dataNode="dn2" ></table>
        <table name="mytb4" primaryKey="id" dataNode="dn2" ></table>
        
       </schema>

	<!-- 資料節點配置-->
	<dataNode name="dn1" dataHost="host1" database="mydb" />
	<dataNode name="dn2" dataHost="host2" database="mydb" />

	
	<dataHost name="host1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="jdbc:mysql://localhost:3306" user="mycat"   password="123456">
			<readHost host="hostS1" url="jdbc:mysql://localhost:3308" user="root"   password="123456" />
		</writeHost>
	</dataHost>
	
	
	<dataHost name="host2" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM2" url="jdbc:mysql://localhost:3307" user="root"   password="123456">
			<readHost host="hostS2" url="jdbc:mysql://localhost:3309" user="root"   password="123456" />
		</writeHost>
	</dataHost>

</mycat:schema>
           

建立資料庫

在資料節點dn1、dn2對應的MySQL上分别建立資料庫mydb

啟動Mycat

[root@administrator bin]# mycat console
Running Mycat-server...
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
jvm 1    |   Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.
jvm 1    | 
jvm 1    | Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
jvm 1    | MyCAT Server startup successfully. see logs in logs/mycat.log
           

開始分庫

通路Mycat:

mysql -umycat -p123456 -h IP -P 8066

進行分庫

mysql> use TESTDB;
Database changed
mysql> CREATE TABLE mytb1(id INT,name VARCHAR(20));
Query OK, 0 rows affected (0.41 sec)

mysql> CREATE TABLE mytb2(id INT,name VARCHAR(20));
Query OK, 0 rows affected (0.40 sec)

mysql> CREATE TABLE mytb3(id INT,name VARCHAR(20));
Query OK, 0 rows affected (0.42 sec)

mysql> CREATE TABLE mytb4(id INT,name VARCHAR(20));
Query OK, 0 rows affected (0.41 sec)

           

驗證分庫

登入

dn1

對應MySQL檢視

mysql> use mydb;
Database changed
mysql> show tables;
+----------------+
| Tables_in_mydb |
+----------------+
| MYTB1          |
| MYTB3          |
+----------------+
2 rows in set (0.00 sec)

mysql> 
           

登入

dn2

對應MySQL檢視

mysql> use mydb;
Database changed
mysql> show tables;
+----------------+
| Tables_in_mydb |
+----------------+
| MYTB2          |
| MYTB4          |
+----------------+
2 rows in set (0.00 sec)

mysql> 
           

實作分表(水準)

配置分片規則

修改

mycat/conf/rule.xml

檔案,配置分片規則

新增分片規則

my_mod_rule

,指定分片字段

id

,選擇分片算法

mod-long:對字段求模運算

<tableRule name="my_mod_rule">
		<rule>
		    <!-- 分片字段: user_id -->
			<columns>id</columns>
			<!-- 分片算法mod-long:對字段求模運算 -->
			<algorithm>mod-long</algorithm>
		</rule>
	</tableRule>

	<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
		<!-- 資料節點2個 -->
		<property name="count">2</property>
	</function>
           

配置schma.xml檔案

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">

       <!-- 将mytb表分到dn1、dn2資料節點,并指定分片規則為my_mod_rule(自定義規則) --> 
       <table name="mytb" primaryKey="id" dataNode="dn1,dn2" rule="my_mod_rule"></table>
        
       </schema>

	<!-- 資料節點配置-->
	<dataNode name="dn1" dataHost="host1" database="mydb" />
	<dataNode name="dn2" dataHost="host2" database="mydb" />

	
	<dataHost name="host1" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="jdbc:mysql://localhost:3306" user="mycat"   password="123456">
			<readHost host="hostS1" url="jdbc:mysql://localhost:3308" user="root"   password="123456" />
		</writeHost>
	</dataHost>
	
	
	<dataHost name="host2" maxCon="1000" minCon="10" balance="0"  writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM2" url="jdbc:mysql://localhost:3307" user="root"   password="123456">
			<readHost host="hostS2" url="jdbc:mysql://localhost:3309" user="root"   password="123456" />
		</writeHost>
	</dataHost>

</mycat:schema>
           

建立資料庫、表

在資料節點dn1、dn2對應的MySQL上分别建立資料庫

mydb

,并建立表

mytb

CREATE DATABASE mydb;

CREATE TABLE mytb(id INT,name VARCHAR(30));
           

啟動Mycat

[root@administrator bin]# mycat console
Running Mycat-server...
wrapper  | --> Wrapper Started as Console
wrapper  | Launching a JVM...
jvm 1    | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
jvm 1    |   Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.
jvm 1    | 
jvm 1    | Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
jvm 1    | MyCAT Server startup successfully. see logs in logs/mycat.log

           

開始分表

通路Mycat:

mysql -umycat -p123456 -h IP -P 8066

進行分表

mysql> use TESTDB;
Database changed

INSERT INTO mytb(id,name) VALUES(1,'mycat1');
INSERT INTO mytb(id,name) VALUES(2,'mycat2');
INSERT INTO mytb(id,name) VALUES(3,'mycat3');
INSERT INTO mytb(id,name) VALUES(4,'mycat4');	
INSERT INTO mytb(id,name) VALUES(5,'mycat5');
INSERT INTO mytb(id,name) VALUES(6,'mycat6');
           

驗證分表

通路Mycat:

mysql -umycat -p123456 -h IP -P 8066

檢視

mysql> use TESTDB;
Database changed

mysql> select * from mytb;
+----+--------+
| ID | NAME   |
+----+--------+
|  2 | mycat2 |
|  4 | mycat4 |
|  6 | mycat6 |
|  1 | mycat1 |
|  3 | mycat3 |
|  5 | mycat5 |
+----+--------+
6 rows in set (0.04 sec)
           

登入

dn1

對應MySQL檢視

mysql> select * from mytb;
+------+--------+
| ID   | NAME   |
+------+--------+
|    2 | mycat2 |
|    4 | mycat4 |
|    6 | mycat6 |
+------+--------+
3 rows in set (0.00 sec)
           

登入

dn2

對應MySQL檢視

mysql> select * from mytb;
+------+--------+
| ID   | NAME   |
+------+--------+
|    1 | mycat1 |
|    3 | mycat3 |
|    5 | mycat5 |
+------+--------+
3 rows in set (0.00 sec)
           

ER表的使用

ER表:基于E-R關系的資料分片政策,子表的記錄與所關聯的父表記錄存放在同一個資料分片上。

作用:進行多表JOIN關聯查詢

配置schema.xml檔案

<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
       <!-- 将mytb表分到dn1、dn2資料節點,并指定分片規則為mod_rule(自定義規則) --> 
       <table name="mytb" primaryKey="id" dataNode="dn1,dn2" rule="my_mod_rule">
       		<!-- 定義ER表 --> 
       		<childTable name="tb_detail" primaryKey="id" joinKey="mytb_id" parentKey="id" />
       </table>        
 </schema>
           

建立資料庫、表

在資料節點dn1、dn2對應的MySQL上分别建立資料庫

mydb

,并建立表

mytb

tb_detail

CREATE DATABASE mydb;

CREATE TABLE mytb(id INT,name VARCHAR(30));

CREATE TABLE mytb(id INT,name VARCHAR(30),mytb_id INT);
           

啟動Mycat

mycat console
           

進行查詢

通路Mycat:

mysql -umycat -p123456 -h IP -P 8066

插入資料

mysql> use TESTDB;
Database changed

INSERT INTO mytb(id,name) VALUES(1,'mycat1');
INSERT INTO mytb(id,name) VALUES(2,'mycat2');
INSERT INTO mytb(id,name) VALUES(3,'mycat3');
INSERT INTO mytb(id,name) VALUES(4,'mycat4');	
INSERT INTO mytb(id,name) VALUES(5,'mycat5');
INSERT INTO mytb(id,name) VALUES(6,'mycat6');


INSERT INTO tb_detail(id,name,mytb_id) VALUES(1,'xq1',1);
INSERT INTO tb_detail(id,name,mytb_id) VALUES(2,'xq2',2);
INSERT INTO tb_detail(id,name,mytb_id) VALUES(3,'xq3',3);
INSERT INTO tb_detail(id,name,mytb_id) VALUES(4,'xq4',4);	
INSERT INTO tb_detail(id,name,mytb_id) VALUES(5,'xq5',5);
INSERT INTO tb_detail(id,name,mytb_id) VALUES(6,'xq6',6);
           

登入

dn1

對應MySQL關聯查詢

mysql> SELECT a.*,b.* FROM mytb a INNER JOIN tb_detail b on a.id=b.mytb_id;
+------+--------+------+------+---------+
| ID   | NAME   | id   | name | mytb_id |
+------+--------+------+------+---------+
|    2 | mycat2 |    2 | xq2  |       2 |
|    4 | mycat4 |    4 | xq4  |       4 |
|    6 | mycat6 |    6 | xq6  |       6 |
+------+--------+------+------+---------+
3 rows in set (0.00 sec)
           

登入

dn2

對應MySQL關聯查詢

mysql> SELECT a.*,b.* FROM mytb a INNER JOIN tb_detail b on a.id=b.mytb_id;
+------+--------+------+------+---------+
| ID   | NAME   | id   | name | mytb_id |
+------+--------+------+------+---------+
|    1 | mycat1 |    1 | xq1  |       1 |
|    3 | mycat3 |    3 | xq3  |       3 |
|    5 | mycat5 |    5 | xq5  |       5 |
+------+--------+------+------+---------+
3 rows in set (0.00 sec)
           

登入

MyCat

關聯查詢

mysql> SELECT a.*,b.* FROM mytb a INNER JOIN tb_detail b on a.id=b.mytb_id;
+----+--------+----+------+---------+
| ID | NAME   | id | name | mytb_id |
+----+--------+----+------+---------+
|  2 | mycat2 |  2 | xq2  |       2 |
|  4 | mycat4 |  4 | xq4  |       4 |
|  6 | mycat6 |  6 | xq6  |       6 |
|  1 | mycat1 |  1 | xq1  |       1 |
|  3 | mycat3 |  3 | xq3  |       3 |
|  5 | mycat5 |  5 | xq5  |       5 |
+----+--------+----+------+---------+
6 rows in set (0.00 sec)
           

全局表的使用

全局表類似于系統中定義的字典表。主要作用是解決資料JOIN的難題。

字典表特點:

變動不頻繁

資料總量變化不大

資料規模不大
           

全局表特點:

全局表的插入、更新操作會實時在所有節點上執行,保持各個分片的資料一緻性

全局表的查詢操作,隻從一個節點擷取

全局表可以跟任何一個表進行 JOIN 操作
           

配置schema.xml檔案

<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">    
	   <!-- 定義全局表 --> 
       <table name="tb_dict" dataNode="dn1,dn2" type="global" ></table> 
 </schema>
           

驗證測試

通路Mycat:

mysql -umycat -p123456 -h IP -P 8066

mysql> use TESTDB;
Database changed

INSERT INTO tb_dict(id,type) VALUES(1,'type1');
INSERT INTO tb_dict(id,type) VALUES(2,'type2');
INSERT INTO tb_dict(id,type) VALUES(3,'type3');
INSERT INTO tb_dict(id,type) VALUES(4,'type4');
           

Mycat查詢

mysql> select * from tb_dict;
+----+-------+
| id | type  |
+----+-------+
|  1 | type1 |
|  2 | type2 |
|  3 | type3 |
|  4 | type4 |
+----+-------+
4 rows in set (0.02 sec)
           

dn1查詢

mysql> select * from tb_dict;
+------+-------+
| id   | type  |
+------+-------+
|    1 | type1 |
|    2 | type2 |
|    3 | type3 |
|    4 | type4 |
+------+-------+
4 rows in set (0.00 sec)
           

dn2查詢

mysql> select * from tb_dict;
+------+-------+
| id   | type  |
+------+-------+
|    1 | type1 |
|    2 | type2 |
|    3 | type3 |
|    4 | type4 |
+------+-------+
4 rows in set (0.00 sec)
           

常用分片規則

1.取模

對分片字段求摸運算,是水準分表最常用規則。
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
       <!-- 将mytb表分到dn1、dn2資料節點,并指定分片規則為my_mod_rule(自定義規則) --> 
       <table name="mytb" primaryKey="id" dataNode="dn1,dn2" rule="my_mod_rule"></table>   
</schema>
           
<tableRule name="my_mod_rule">
		<rule>
		    <!-- 分片字段: user_id -->
			<columns>id</columns>
			<!-- 分片算法mod-long:對字段求模運算 -->
			<algorithm>mod-long</algorithm>
		</rule>
	</tableRule>

	<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
		<!-- 資料節點2個 -->
		<property name="count">2</property>
	</function>
           

2.範圍約定

在配置檔案中配置,适用于提前規劃好分片字段某個範圍屬于哪個分片。
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
       <!-- 将mytb表分到dn1、dn2資料節點,并指定分片規則為auto-sharding-long(自帶分片規則) --> 
       <table name="mytb" primaryKey="id" dataNode="dn1,dn2" rule="auto-sharding-long"></table>   
</schema>
           

修改

rule.xml

配置檔案,使用預設如下配置即可

<tableRule name="auto-sharding-long">
		<rule>
			 <!-- 分片字段 -->
			<columns>id</columns>
			<!-- 分片函數 -->
			<algorithm>rang-long</algorithm>
		</rule>
	</tableRule>
	
	<function name="rang-long"
			  class="io.mycat.route.function.AutoPartitionByLong">
		<!-- 辨別配置檔案名稱 -->	  
		<property name="mapFile">autopartition-long.txt</property>
	</function>
           

修改

/mycat/conf/autopartition-long.txt

,預設配置如下

# range start-end ,data node index
# K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2
           

修改配置如下:

0-19=0
20-40=1
           

通路Mycat:

mysql -umycat -p123456 -h IP -P 8066

插入資料

INSERT INTO mytb(id,name) VALUES(5,'mycat1');
INSERT INTO mytb(id,name) VALUES(10,'mycat2');
INSERT INTO mytb(id,name) VALUES(20,'mycat3');
INSERT INTO mytb(id,name) VALUES(25,'mycat4');	
           

查詢

mysql> select * from mytb;

+----+--------+
| ID | NAME   |
+----+--------+
|  5 | mycat1 |
| 10 | mycat2 |
| 20 | mycat3 |
| 25 | mycat4 |
+----+--------+
4 rows in set (0.01 sec)
           

登入dn1對應MySQL查詢

mysql> select * from mytb;
+------+--------+
| ID   | NAME   |
+------+--------+
|    5 | mycat1 |
|   10 | mycat2 |
+------+--------+
3 rows in set (0.00 sec)
           

登入dn2對應MySQL查詢

mysql> select * from mytb;
+------+--------+
| ID   | NAME   |
+------+--------+
|   20 | mycat3 |
|   25 | mycat4 |
+------+--------+
3 rows in set (0.00 sec)
           

3.分片枚舉

在配置檔案中配置可能的枚舉 id,自己配置分片
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
       <!-- 将mytb表分到dn1、dn2資料節點,并指定分片規則為sharding-by-intfile(自帶分片規則) --> 
       <table name="mytb" primaryKey="id" dataNode="dn1,dn2" rule="sharding-by-intfile"></table>   
</schema>
           
<tableRule name="sharding-by-intfile">
		<rule>
			<columns>sharding_id</columns>
			<algorithm>hash-int</algorithm>
		</rule>
	</tableRule>
	
	<function name="hash-int"
			  class="io.mycat.route.function.PartitionByFileMap">
		<property name="mapFile">partition-hash-int.txt</property>
	</function>
           

/mycat/conf/partition-hash-int.txt

預設配置

10000=0
10010=1
           

解釋:

當插入資料庫中指定的分區字段=10000則該資料劃分到dn1

當插入資料庫中指定的分區字段=10010則該資料劃分到dn2
           

4.按日期、天分片

<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
       <!-- 将mytb表分到dn1、dn2資料節點,并指定分片規則為sharding-by-date(自帶分片規則) --> 
       <table name="mytb" primaryKey="id" dataNode="dn1,dn2" rule="sharding-by-date"></table>   
</schema>
           

rule.xml

配置檔案

<tableRule name="sharding-by-date">
		<rule>
		    <!-- 分片字段 -->
			<columns>createTime</columns>
			<!-- 分片函數 -->
			<algorithm>partbyday</algorithm>
		</rule>
	</tableRule>
	
	<function name="partbyday"
			  class="io.mycat.route.function.PartitionByDate">
		<!-- 日期格式 -->
		<property name="dateFormat">yyyy-MM-dd</property>
		<property name="sNaturalDay">0</property>
		<!-- 開始日期 -->
		<property name="sBeginDate">2014-01-01</property>
		<!-- 結束日期:代表資料達到這個日期的分片後循環從開始分片插入 -->
		<property name="sEndDate">2014-01-31</property>
		<!-- 分區天數,預設從開始日期算起,每隔10天一個分區 -->
		<property name="sPartionDay">10</property>
	</function>
           

分片函數解釋:

從開始日期

2014-01-01

開始到

2014-01-10

共10天,這10天屬于一個分區,如dn1
從開始日期

2014-01-11

開始到

2014-01-20

共10天,這10天屬于另一個分區,如dn2
從開始日期

2014-01-21

開始到

2014-01-30

共10天,這10天屬于另一個分區,如dn3
從開始日期

2014-01-31

開始到

2014-02-9

共10天,

2014-01-31

是結束時間,開始循環,這10天就屬于dn1

全局序列

在實作分庫分表的情況下,資料庫自增主鍵已無法保證自增主鍵的全局唯一。Mycat 提供了全局 sequence,并且提供了包含本地配置和資料庫配置等多種實作方式

全局序列方案

1.本地檔案

Mycat将sequence配置到檔案中,當使用到sequence中的配置後,Mycat會更新如

classpath

中的

sequence_conf.properties

檔案中sequence目前值
本地加載,讀取速度較快。但是抗風險能力差,Mycat所在主機當機後,無法讀取本地檔案

2.資料庫方式

利用資料庫一個表來進行計數累加。Mycat會預加載一部分号段到Mycat的記憶體中,這樣大部分讀寫序列都是在記憶體中完成的。如果記憶體中的号段用完了 Mycat 會再向資料庫要一次。
如果Mycat崩潰了,則記憶體中的序列就沒了,就損失了目前的号段沒用完的号碼,但是不會是以出現主鍵重複。當Mycat啟動後會向資料庫申請新的号段,原有号段會棄用

3.時間戳方式

全局序列ID=64位二進制,換算成十進制為18位數的long類型,每毫秒可以并發12位二進制的累加。配置簡單,但是18位ID過長

64位ID可以分成5個部分:

1位符号位辨別 - 41位時間戳 - 5位資料中心辨別 - 5位機器辨別 - 12位序列号
           
MyCat中對分庫分表、ER表、全局表、分片規則、全局序列等的實作與基本使用操作分庫分表概念實作分庫(垂直)實作分表(水準)ER表的使用全局表的使用常用分片規則全局序列

4.自主生成全局序列

在項目中根據具體業務邏輯定義生成全局序列,如使用redis單線程原子性incr來生成序列。但是需要單獨在項目中實作具體邏輯,推薦使用Mycat自帶全局序列

資料庫方式實作全局序列

建庫建表

全局序列SQL檔案:

/mycat/conf/dbseq.sql

,在

dn1

上建立全局序清單

1.建立全局序清單

DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (  name VARCHAR(64) NOT NULL,  current_value BIGINT(20) NOT NULL,  increment INT NOT NULL DEFAULT 1, PRIMARY KEY (name) ) ENGINE=InnoDB;
           

2.建立全局序列所需函數

DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_currval`(seq_name VARCHAR(64)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    SET retval="-1,0";
    SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval FROM MYCAT_SEQUENCE  WHERE name = seq_name;
    RETURN retval ;
END
;;
DELIMITER ;


DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(64)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE val BIGINT;
    DECLARE inc INT;
    DECLARE seq_lock INT;
    set val = -1;
    set inc = 0;
    SET seq_lock = -1;
    SELECT GET_LOCK(seq_name, 15) into seq_lock;
    if seq_lock = 1 then
      SELECT current_value + increment, increment INTO val, inc FROM MYCAT_SEQUENCE WHERE name = seq_name for update;
      if val != -1 then
          UPDATE MYCAT_SEQUENCE SET current_value = val WHERE name = seq_name;
      end if;
      SELECT RELEASE_LOCK(seq_name) into seq_lock;
    end if;
    SELECT concat(CAST((val - inc + 1) as CHAR),",",CAST(inc as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;


DROP FUNCTION IF EXISTS `mycat_seq_nextvals`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_nextvals`(seq_name VARCHAR(64), count INT) RETURNS VARCHAR(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE val BIGINT;
    DECLARE seq_lock INT;
    SET val = -1;
    SET seq_lock = -1;
    SELECT GET_LOCK(seq_name, 15) into seq_lock;
    if seq_lock = 1 then
        SELECT current_value + count INTO val FROM MYCAT_SEQUENCE WHERE name = seq_name for update;
        IF val != -1 THEN
            UPDATE MYCAT_SEQUENCE SET current_value = val WHERE name = seq_name;
        END IF;
        SELECT RELEASE_LOCK(seq_name) into seq_lock;
    end if;
    SELECT CONCAT(CAST((val - count + 1) as CHAR), ",", CAST(val as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;


DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_setval`(seq_name VARCHAR(64), value BIGINT) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE inc INT;
    SET inc = 0;
    SELECT increment INTO inc FROM MYCAT_SEQUENCE WHERE name = seq_name;
    UPDATE MYCAT_SEQUENCE SET current_value = value WHERE name = seq_name;
    SELECT concat(CAST(value as CHAR),",",CAST(inc as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;
           

3.初始化序清單記錄

修改sequence_db_conf.properties配置

修改

/mycat/conf/sequence_db_conf.properties

,預設配置如下

#sequence stored in datanode
GLOBAL=dn1
COMPANY=dn1
CUSTOMER=dn1
ORDERS=dn1
           

GLOBAL=dn1

:表示序清單

GLOBAL

指定在dn1節點上

注意:

初始化那個序清單,這裡就配置那個表,比如如下初始化

GLOBAL

序清單

修改 server.xml

修改

/mycat/conf/server.xml

,設定全局序列類型

全局序列類型:

0:本地檔案

1:資料庫方式,預設

2:時間戳方式
           

配置schema.xml檔案

修改

schema.xml

檔案,配置

MYCAT_SEQUENCE

序清單

<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">

       <!-- 将mytb1表分到dn1、dn2資料節點,并指定分片規則為mod_rule(自定義規則) --> 
       <table name="mytb" primaryKey="id" dataNode="dn1,dn2" rule="my_mod_rule"> </table>
       <table name="MYCAT_SEQUENCE" dataNode="dn1"> </table>
       </schema>
           

驗證全局序列

查詢

MYCAT_SEQUENCE

mysql> SELECT * FROM MYCAT_SEQUENCE;
+--------+---------------+-----------+
| name   | current_value | increment |
+--------+---------------+-----------+
| GLOBAL |             1 |         1 |
+--------+---------------+-----------+
1 row in set (0.01 sec)
           

mytb

表插入資料

insert into mytb(id,name) values(next value for MYCATSEQ_GLOBAL,'mycat1');
insert into mytb(id,name) values(next value for MYCATSEQ_GLOBAL,'mycat2');
insert into mytb(id,name) values(next value for MYCATSEQ_GLOBAL,'mycat3');
insert into mytb(id,name) values(next value for MYCATSEQ_GLOBAL,'mycat4');
           
mysql> select * from mytb;
+----+--------+
| ID | NAME   |
+----+--------+
|  2 | mycat1 |
|  4 | mycat3 |
|  1 | mycat1 |
|  3 | mycat2 |
|  5 | mycat4 |
+----+--------+
5 rows in set (0.01 sec)
           

查詢

MYCAT_SEQUENCE

表,目前值記錄到5了。

mysql> SELECT * FROM MYCAT_SEQUENCE;
+--------+---------------+-----------+
| name   | current_value | increment |
+--------+---------------+-----------+
| GLOBAL |             5 |         1 |
+--------+---------------+-----------+
1 row in set (0.00 sec)