MyCat中对分库分表、ER表、全局表、分片规则、全局序列等的实现与基本使用操作

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 MyCat中对分库分表、ER表、全局表、分片规则、全局序列等的实现与基本使用操作,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

分库分表概念

分库

分库又分为:水平分库与垂直分库

水平分库:把同一个表的数据按一定规则拆到不同的数据库中

垂直分库:按照业务、功能模块将表进行分类,不同功能模块对应的表分到不同的库中

分库原则:将紧密关联关系的表划分在一个库里,没有关联关系的表可以分到不同的库里

分表

分表又分为:水平分表与垂直分表

水平分表:在同一个数据库内,把同一个表的数据按一定规则拆到多个表中

垂直分表:将一个表按照字段分成多表,每个表存储其中一部分字段

分表原则:减少节点数据库的访问,分表字段尤为重要,其决定了节点数据库的访问量。

实现分库(垂直)

配置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

CREATE DATABASE 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,并创建表mytbtb_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位序列号

在这里插入图片描述
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.初始化序列表记录

INSERT INTO MYCAT_SEQUENCE VALUES ('GLOBAL', 1, 1);

修改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序列表

INSERT INTO MYCAT_SEQUENCE VALUES ('GLOBAL', 1, 1);

修改 server.xml

修改/mycat/conf/server.xml,设置全局序列类型

<property name="sequenceHandlerType">1</property>

全局序列类型:

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)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136926.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!