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
共10天,這10天屬于一個分區,如dn1
2014-01-10
從開始日期開始到
2014-01-11
共10天,這10天屬于另一個分區,如dn2
2014-01-20
從開始日期開始到
2014-01-21
共10天,這10天屬于另一個分區,如dn3
2014-01-30
從開始日期開始到
2014-01-31
共10天,
2014-02-9
是結束時間,開始循環,這10天就屬于dn1
2014-01-31
全局序列
在實作分庫分表的情況下,資料庫自增主鍵已無法保證自增主鍵的全局唯一。Mycat 提供了全局 sequence,并且提供了包含本地配置和資料庫配置等多種實作方式
全局序列方案
1.本地檔案
Mycat将sequence配置到檔案中,當使用到sequence中的配置後,Mycat會更新如中的
classpath
檔案中sequence目前值
sequence_conf.properties
本地加載,讀取速度較快。但是抗風險能力差,Mycat所在主機當機後,無法讀取本地檔案
2.資料庫方式
利用資料庫一個表來進行計數累加。Mycat會預加載一部分号段到Mycat的記憶體中,這樣大部分讀寫序列都是在記憶體中完成的。如果記憶體中的号段用完了 Mycat 會再向資料庫要一次。
如果Mycat崩潰了,則記憶體中的序列就沒了,就損失了目前的号段沒用完的号碼,但是不會是以出現主鍵重複。當Mycat啟動後會向資料庫申請新的号段,原有号段會棄用
3.時間戳方式
全局序列ID=64位二進制,換算成十進制為18位數的long類型,每毫秒可以并發12位二進制的累加。配置簡單,但是18位ID過長
64位ID可以分成5個部分:
1位符号位辨別 - 41位時間戳 - 5位資料中心辨別 - 5位機器辨別 - 12位序列号
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI2EzX4xSZz91ZsAzNfRHLGZkRGZkRfJ3bs92YsAjMfVmepNHLvlGT1UnVHFGR5ETYqZUbT9WaMVTQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3kTM5UDN5IDOyEjMyEGZiRGMmRDOkNGNxgTZiVWY2Y2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
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)