分库分表概念
分库
分库又分为:水平分库与垂直分库
水平分库
:把同一个表的数据按一定规则拆到不同的数据库中
垂直分库
:按照业务、功能模块将表进行分类,不同功能模块对应的表分到不同的库中
分库原则
:将紧密关联关系的表划分在一个库里,没有关联关系的表可以分到不同的库里
分表
分表又分为:水平分表与垂直分表
水平分表
:在同一个数据库内,把同一个表的数据按一定规则拆到多个表中
垂直分表
:将一个表按照字段分成多表,每个表存储其中一部分字段
分表原则
:减少节点数据库的访问,分表字段尤为重要,其决定了节点数据库的访问量。
实现分库(垂直)
配置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
,并创建表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位序列号
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