MyCat分库分表

本章重点

  • mycat分表分库技术(横向数据切分)

  • mycat数据切分规则(取余分库,自然月分库)

  • mycat全局序列号(实现mysql集群主键ID全局自增)

一、分库分表

简单来说,就是指通过某种特定的条件(分片规则),将我们存放在同一个数据库中的数据分散存放到多个数据库(主机) 上面,以达到分散单台设备负载的效果。

分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分成若干数据库组成,将数据大表分成若干数据表组成,使得单一数据库、单一数据表的数据量变小,从而达到提升数据库性能的目的。随着微服务这种架构的兴起,应用从一个完整的大的应用,切分为很多可以独立提供服务的小应用。每个应用都有独立的数据库。

1.1 为什么要分库分表

  • 表太长

  • 减轻数据库压力

  • 数据太多,数据并发太大了

  • id用完了

  • 查询太慢了

1.2 分库分表类型

数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式:

  • 垂直切分:按照业务模块进行切分,将不同模块的表切分到不同的数据库中。

  • 水平切分:将一张大表按照一定的切分规则,按照行切分到不同的表或者不同的库中。

1.2.3 垂直切分

一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面。这种七分可以称之为数据的垂直(纵向)切分。

  • ==垂直分库==:是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放不同的服务器上

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

把一个原来43表库分成4个不同的库:

优点:

  • 拆分后业务清晰,拆分规则明确;

  • 系统之间整合或扩展容易;

  • 数据维护简单。(原来我要维护43表,每张表意义级表之间的关联要理清 ,现在每个库都有10张左右的表,每张表意义级表之间的关联更容易理清)

缺点:

  • 部分业务表无法join,只能通过接口方式解决,提高了系统复杂度;(当需要跨系统做业务时,难度加大。例如会员管理要调用车辆管理的数据,就需要先获取会员数据,再另一个项目的车辆数据,在服务层拼装)

  • 受每种业务不同的限制存在单库性能瓶颈(单表数据量过大的问题),不易数据扩展跟性能提高;

  • 事务处理复杂(一个业务既要向会员表添加数据,还要向车辆表添加数据,如果在同一个项目中,只要使用spring声明式事务即可。但现在两张表在不同的库中,不可以使用spring声明式事务, 需要使用分布式事务,难度会加大)

1.2.2 水平切分

一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。

相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中 包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中。

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

  • 水平分库:是把同一个表的数据按一定规则拆分到不同的数据库中,每个库可以放不同的服务器上

某个字段的某种规则:根据用户ID对分表分库总数量取余方式,把数据放入不同的库。

优点:

  • 拆分规则抽象好,join 操作基本可以数据库做(数据库中间件为我们实现功能)

  • 不存在单库大数据,高并发的性能瓶颈;(把数据库量大的表,都进行拆开,不存在单表数据量大的问题)

  • 应用端改造较少

  • 提高了系统的稳定性跟负载能力。

缺点:

  • 拆分规则难以抽象;(拆分规则复杂)

  • 分片事务一致性难以解决;(分布式事务问题)

  • 数据多次扩展难度跟维护量极大;

  • 跨库 join 性能较差(跨网络请求库)

二、MyCat垂直分库实现

在两台主机上的两个数据库中的表,不可以关联查询。

分库的原则:

有紧密关联关系的表应该在一个库里,相互没有关联关系的表可以分到不同的库里。

2.1 准备

结构如下:

  • 用户数据:保存在数据库db1中,如用户表,角色表,权限表...

  • 订单数据:保存在数据库db2中,如订单表,订单详情表,订单状态字典表...

  • 商品数据:保存在数据库db3中,如商品类型,商品详情...

  1. 准备三台mysql数据库服务器

  2. 启动数据库服务,在三台mysql数据库中分别创建数据库db1,db2,db3

2.2 修改server.xml

定义连接用户

2.3 修改schema配置文件

2.4 测试

  1. 启动mycat服务

  2. 连接mycat

  1. 在mycat数据库中,执行以下SQL语句,创建数据库表

CREATE TABLE `user_info` (`user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',`user_name` varchar(32) DEFAULT NULL COMMENT '账号',`user_nickname` varchar(32) DEFAULT NULL COMMENT '昵称',`user_phone` varchar(13) DEFAULT NULL COMMENT '手机',`user_email` varchar(32) DEFAULT NULL COMMENT '邮箱',`user_pass` varchar(64) DEFAULT NULL COMMENT '密码',`user_state` int(11) DEFAULT NULL COMMENT '状态0 激活 1 未激活 2 禁用',PRIMARY KEY (`user_id`)
);
​
​
CREATE TABLE `order_info` (`order_num` varchar(64) NOT NULL COMMENT '订单编号',`user_id` int(11) DEFAULT NULL COMMENT '用户ID',`address_info` varchar(128) DEFAULT NULL COMMENT '地址详情',`receiver_name` varchar(32) DEFAULT NULL COMMENT '收货人',`receiver_phone` varchar(13) DEFAULT NULL COMMENT '收货人电话',`order_price` decimal(10,2) DEFAULT NULL COMMENT '订单总价',`create_time` datetime DEFAULT NULL COMMENT '下单时间',`pay_time` datetime DEFAULT NULL COMMENT '支付时间',`order_state` int(11) DEFAULT NULL COMMENT '状态0 未支付 1 已支付  2 已取消 3 待评价 4 已完成 5 已退款',PRIMARY KEY (`order_num`)
);
​
​
CREATE TABLE `book_type` (`type_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',`type_name` varchar(64) DEFAULT NULL COMMENT '类别名字',`parent_id` int(11) DEFAULT NULL COMMENT '父ID,0就代表没有',`type_state` int(11) DEFAULT NULL COMMENT '状态0 可用 1 删除 2 禁用',`type_self` int(11) DEFAULT NULL COMMENT '是否是叶子节点 0是 1否',PRIMARY KEY (`type_id`)
);

发现数据表进入对应的数据库,分库实现成功

  1. 执行添加数据库操作,可以加入对应的数据库数据表中

INSERT INTO `user_info`(`user_id`, `user_name`, `user_nickname`, `user_phone`, `user_email`, `user_pass`, `user_state`) 
VALUES (null, 'admin', 'admin', '18523599358', '123@qq.com', '123456', 0);

三、MyCat水平分表实现

3.1 准备

假定预测到order_info订单表,数据量将会巨大(数据量超过1000W或者单表大小超过100G),进行分表分库操作,把订单表的数据进行水平切分,放入不同数据库的不同表中。

结构如下:

  1. 新建分片数据库:db1,db2,db3

  2. 在db1,db2,db3数据库下,新建数据库表tb_order

    ==注意:数据库名可以不一致,但是每个数据库下的分片表名必须一致==

create table tb_order(id int  primary key comment  '只能是主键不能自增',clientid int comment '客户id',goods_id int comment '商品id',shop_id int  comment '商店Id',create_time datetime comment '下单时间',shard_date  date comment '分片时间' 
);

3.2 server.xml配置

同上,不切换逻辑数据库和用户不需要重新配置

3.3 schema.xml配置

新增rule数据,配置数据表分片规则,规则名与rule.xml中声明的一致

3.4 rule.xml配置

分片规则配置文件

  • tablerule:这个标签定义表规则。

    • name:指定唯一的名字( 随便命名,和shema.xml中的table上rule属性名称对应),用于标识不同的表规则。 内嵌的 rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。

    • columns:内指定要拆分的数据库列名字

    • algorithm:使用 function 标签中的 name 属性。连接表规则和具体路由算法。当然,多个表规则可以连接到 同一个路由算法上。table 标签内使用。让逻辑表使用这个规则进行分片。

  • function:

    • name:指定算法的名字

    • class:制定路由算法具体的类名字

    • property:为具体算法需要用到的一些属性

3.4 测试

  1. 配置完成后,启动mycat服务

  2. 连接mycat,执行新增操作:表中列名称必须写

insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1001,11,10001,101,now(),now());
insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1002,12,10001,101,now(),now());
insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1003,13,10001,101,now(),now());
insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1004,14,10001,101,now(),now());
insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1005,15,10001,101,now(),now());
insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1006,16,10001,101,now(),now());
insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1007,17,10001,101,now(),now());
insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1008,18,10001,101,now(),now());
insert into  tb_order(id,clientid,goods_id,shop_id,create_time,shard_date) values(1009,19,10001,101,now(),now());
  1. 发现对应数据保存到对应的数据库中

按id取余(mod)分片,跟据插入数据的id:

1001%3 =1,该数据就放入编号为0的第2个库中

1002%3 =2,该数据就放入编号为1的第3个库中

1003%3 =0,该数据就放入编号为2的第1个库中

使用mycat查询,可以查到所有数据

四、MyCat分片规则

4.1 取模

此规则为对分片字段求摸运算。

<tableRule name="mod-long"><rule><columns>user_id</columns><algorithm>mod-long</algorithm></rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod"><!-- how many data nodes --><property name="count">3</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
count分片数量

根据 id 进行十进制求模预算,相比固定分片 hash,此种在批量插入时可能存在批量插入单事务插入多数据分片,增大事务一致性难度。

4.2 范围约定

此分片适用于,提前规划好分片字段某个范围属于哪个分片。

<tableRule name="auto-sharding-long"><rule><columns>user_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><property name="defaultNode">0</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
mapFile标识配置文件名称
defaultNode超过范围后的默认节点

所有的节点配置都是从 0 开始,及 0 代表节点 1,此配置非常简单,即预先制定可能的 id 范围到某个分片:

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

4.3 范围求模分片

先进行范围分片计算出分片组,组内再求模。

优点可以避免扩容时的数据迁移,又可以一定程度上避免范围分片的热点问题。综合了范围分片和求模分片的优点,分片组内使用求模可以保证组内数据比较均匀,分片组之间是范围分片,可以兼顾范围查询。

最好事先规划好分片的数量,数据扩容时按分片组扩容,则原有分片组的数据不需要迁移。由于分片组内数据比较均匀,所以分片组内可以避免热点数据问题。

<tableRule name="auto-sharding-rang-mod"><rule><columns>id</columns><algorithm>rang-mod</algorithm></rule>
</tableRule>
<function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod"><property name="mapFile">partition-range-mod.txt</property><property name="defaultNode">21</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
mapFile配置文件路径
defaultNode超过范围后的默认节点顺序号,节点从 0 开始。
partition-range-mod.txt
# 以下配置一个范围代表一个分片组,=号后面的数字代表该分片组所拥有的分片的数量。
# range start-end ,data node group size
0-200M=5 //代表有 5 个分片节点
200M1-400M=1
400M1-600M=4
600M1-800M=4
800M1-1000M=6

注意

如上0-200M存入到5个分片中,开始范围-结束范围=该分片组有多少个分片。如果超过配置范围需要增加分片组。

4.4 按日期(天)分片

此规则为按天分片。

<tableRule name="sharding-by-date"><rule><columns>create_time</columns><algorithm>sharding-by-date</algorithm></rule>
</tableRule>
<function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate"><property name="dateFormat">yyyy-MM-dd</property><property name="sBeginDate">2014-01-01</property><property name="sEndDate">2014-01-02</property><property name="sPartionDay">10</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
dateForma日期格式
sBeginDate开始日期
sEndDate结束日期
sPartionDay分区天数,即默认从开始日期算起,分隔 10 天一个分区

如果配置了 sEndDate 则代表数据达到了这个日期的分片后循环从开始分片插入。

注意

在查询时,如果需要查询时间段应该使用between...and,使用>=或者<=会查询所有分片。

4.5 自然月分片

按月份列分区 ,每个自然月一个分片,格式 between 操作解析的范例。

<tableRule name="sharding-by-month"><rule><columns>create_time</columns        ><algorithm>sharding-by-month</algorithm></rule>
</tableRule>
<function name="sharding-by-month" class="io.mycat.route.function.PartitionByMonth"><property name="dateFormat">yyyy-MM-dd</property><property name="sBeginDate">2014-01-01</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
dateFormat日期格式
sBeginDate开始日期(无默认值)
sEndDate结束日期(无默认值)

注意

  1. 默认设置,节点数量必须是12个,每12个月循环从开始分片插入

  2. 如配置了sBeginDate="2019-01"月是第0个分片,从该时间按月递增,无最大节点

  3. 配置了sBeginDate = "2015-01-01"sEndDate = "2015-12-01"该配置可以看成和第一个一致

  4. 配置了sBeginDate = "2015-01-01"sEndDate = "2015-03-01"该配置标识只有 3 个节点;很难与月份对应上;平均分散到 3 个节点上

4.6 日期范围HASH分片

思想与范围求模一致,当由于日期在取模会有数据集中问题,所以改成 hash 方法。先根据日期分组,再根据时间 hash 使得短期内数据分布的更均匀。

优点可以避免扩容时的数据迁移,又可以一定程度上避免范围分片的热点问题。要求日期格式尽量精确些,不然达不到局部均匀的目的

<tableRule name="range-date-hash"><rule><columns>col_date</columns><algorithm>range-date-hash</algorithm></rule>
</tableRule>
<function name="range-date-hash" class="io.mycat.route.function.PartitionByRangeDateHash"><property name="sBeginDate">2014-01-01 00:00:00</property><property name="sPartionDay">365</property><property name="dateFormat">yyyy-MM-dd HH:mm:ss</property><property name="groupPartionSize">3</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
sBeginDate开始日期
sPartionDay多少天一个分片
dateFormat日期格式
groupPartionSize分片组的大小

注意

从sBeginDate时间开始计算,每sPartionDay天的数据为一个分片组,每个分片组可以分布在groupPartionSize个分片上面。上面的例子最多可以有三天进行分片,如果超出则会抛出以下异常。

Cause: com.mysql.jdbc.exceptions.jd        bc4.MySQLSyntaxErrorException: Can't find a valid data node for specified node index :ALAN_TEST -> RANGE_DATE -> 2019-01-11 12:00:00 -> Index : 4
The error may involve com.mycat.test.model.AlanTest.insert-Inline
The error occurred while setting parameters

4.7 按单月小时拆分

此规则是单月内按照小时拆分,最小粒度是小时,可以一天最多 24 个分片,最少 1 个分片,一个月完后下月从头开始循环。每个月月尾,需要手工清理数据。

<tableRule name="sharding-by-hour"><rule><columns>create_time</columns><algorithm>sharding-by-hour</algorithm></rule>
</tableRule>
<function name="sharding-by-hour" class="io.mycat.route.function.LatestMonthPartion"><property name="splitOneDay">24</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段(字符串类型yyyyMMddHH)
algorithm分片函数
splitOneDay一天切分的分片数

注意

分片字段必须为字符串格式,否则分片不成功,默认存到第一个分片里面; 保存的时间格式必须为"yyyymmddHH"格式,不能多也不能少字符,否则分片不成功,默认存到第一个分片里面;

4.8 分片枚举

通过在配置文件中配置可能的枚举 id,自己配置分片,本规则适用于特定的场景,比如有些业务需要按照省份或区县来做保存,而全国省份区县固定的,这类业务使用本条规则,配置如下:

<tableRule name="sharding-by-intfile"><rule><columns>user_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><property name="type">0</property><property name="defaultNode">0</property>
</function>

配置说明

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
mapFile标识配置文件名称
type默认值为 0,0 表示 Integer,非零表示 String
defaultNode默认节点:小于 0 表示不设置默认节点,大于等于 0 设置默认节点

partition-hash-int.txt 配置:

10000=0
10010=1
DEFAULT_NODE=1      //默认节点

默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点,如果不配置默认节点(defaultNode 值小于 0 表示不配置默认节点),碰到不识别的枚举值就会报错

like this:can’t find datanode for sharding column:column_name val:ffffffff

4.9 固定分片 hash 算法

本条规则类似于十进制的求模运算,区别在于是二进制的操作,是取 id 的二进制低 10 位,即 id 二进制 &1111111111。

此算法的优点在于如果按照 10 进制取模运算,在连续插入 1-10 时候 1-10 会被分到 1-10 个分片,增大了插入的事务控制难度,而此算法根据二进制则可能会分到连续的分片,减少插入事务事务控制难度。

<tableRule name="rule1"><rule><columns>user_id</columns><algorithm>func1</algorithm></rule>
</tableRule>
<function name="func1" class="io.mycat.route.function.PartitionByLong"><property name="partitionCount">2,1</property><property name="partitionLength">256,512</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
partitionCount分片个数列表
partitionLength分片范围列表

分区长度:

默认为最大 2^n=1024 ,即最大支持 1024 分区。

约束:

count,length 两个数组的长度必须是一致的;

1024 = sum((count[i]*length[i]))

count 和 length 两个向量的点积恒等于 1024。

如果需要平均分配设置:平均分为 4 分片,partitionCount*partitionLength=1024。

<function name="func1" class="io.mycat.route.function.PartitionByLong"><property name="partitionCount">4</property><property name="partitionLength">256</property>
</function>

4.10 截取数字 hash 解析

此规则是截取字符串中的 int 数值 hash 分片。

<tableRule name="sharding-by-stringhash"><rule><columns>user_id</columns><algorithm>sharding-by-stringhash</algorithm></rule>
</tableRule>
<function name="sharding-by-stringhash" class="io.mycat.route.function.PartitionByString"><property name="partitionLength">512</property><!-- zero-based --><property name="partitionCount">2</property><property name="hashSlice">0:2</property>
</function>

配置说明:

标签属性说明
columns标识将要分片的表字段
algorithm分片函数
partitionLength字符串hash求模基数
partitionCount分区数
hashSlice预算位,即根据子字符串中 int 值 hash 运算。 0 means str.length(), -1 means str.length()-1

注意

hashSlice可以理解为substring(start,end),start为0则只表示0; 例1:值“45abc”,hash预算位0:2 ,取其中45进行计算 例2:值“aaaabbb2345”,hash预算位-4:0 ,取其中2345进行计算

五、MyCat全局序列号

在实现分库分表的情况下,数据库自增主键已无法保证自增主键的全局唯一(分片后,每个表主键id不能像过去一样,各自设置自增,如果设置,在mycat中查询id就会重复。为此,MyCat 提供了全局 sequence,并且提供了包含本地配置和数据库配置等多种实现方式。

5.1 sequnceHandlerType

序列号处理器类型

  • 0: 本地文件方式(sequence_conf.properties)

  • 1: 数据库方式(MYCAT_SEQUENCE表、sequence_db_conf.properties)

  • 2: 本地时间戳方式(sequence_time_conf.properties)

  • 3: 分布式ZK ID生成器

  • 4: ZK递增方式

server.xml 中配置:

<system><property name="sequnceHandlerType">0</property>
</system>
注:sequnceHandlerType 配置为0表示使用本地文件读取。

5.2 本地文件方式

原理:

此方式 MyCAT 将 sequence 配置到文件中,当使用到 sequence 中的配置后,MyCAT 会更下 classpath 中的 sequence_conf.properties 文件中 sequence 当前的值。

配置方式:

在MyCat的conf目录下,找到sequence_conf.properties文件。这个文件包含了序列的相关配置信息,如各个表或全局序列的最大值、当前值、历史值等。

vim /usr/mycat-sharding/mycat/conf/sequence_conf.properties
# 全局配置
GLOBAL.HISIDS=
GLOBAL.MINID=1001        
GLOBAL.MAXID=100000000
GLOBAL.CURID=1000
​
# 表配置,USERS是server.xml中配置的table name的大写
USERS.HISIDS=
USERS.MINID=1001
USERS.MAXID=100000000
USERS.CURID=1000

配置项说明:

  • XXX.MAXID:表示某个表或全局序列的最大ID值。

  • XXX.CURID:表示某个表或全局序列的当前ID值。

  • XXX.HISIDS:表示某个表或全局序列的历史ID值(通常用于记录已经使用过的ID,以避免重复)。

序列值的更新和使用:

  • 更新:当应用程序从MyCat获取并使用一个序列值时,MyCat会更新sequence_conf.properties文件中对应的序列当前值。

  • 使用:在应用程序中,可以通过SQL语句如SELECT NEXT_VALUE FOR global_seq;来获取全局序列的下一个值。

重启服务:

/usr/mycat-sharding/mycat/bin/mycat restart

测试查询下一个值:

select next value for MYCATSEQ_GLOBAL;
select next value for MYCATSEQ_TB_TEST;
​
select next value for MYCATSEQ_序列名;

使用示例:

insert into tb_order(id,clientid,goods_id,shop_id,create_time,shard_date)
values(next value for MYCATSEQ_GLOBAL,19,10001,101,now(),'2022-01-22');
​
insert into tb_order(id,clientid,goods_id,shop_id,create_time,shard_date)
values(next value for MYCATSEQ_GLOBAL,19,10001,101,now(),'2022-02-22');
​
insert into tb_order(id,clientid,goods_id,shop_id,create_time,shard_date)
values(next value for MYCATSEQ_GLOBAL,19,10001,101,now(),'2022-03-22');

5.3 数据库方式

在数据库中建立一张表,存放sequence名称、sequence当前值、步长等信息。MyCat负责维护这张表,并读取和更新sequence值。

vim sequence_db_conf.properties
<property name="sequnceHandlerType">1</property>

创建和维护全局序列号数据库表:

在MyCat后端连接的某个数据库中,创建一个用于存储全局序列号信息的表。这个表通常包含序列名称、当前值、步长等信息。

在数据库(db1,db2,db3任意)下执行SQL,创建索引表和函数:

DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (
NAME VARCHAR (50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 100,
PRIMARY KEY (NAME)
) ENGINE = INNODB ;
​
DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) 
RETURNS VARCHAR(64) CHARSET utf8DETERMINISTIC
BEGIN DECLARE retval VARCHAR(64);SET retval="-999999999,null";  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(50)) RETURNS VARCHAR(64)CHARSET utf8DETERMINISTIC
BEGIN UPDATE MYCAT_SEQUENCE  SET current_value = current_value + increment WHERE NAME = seq_name;  RETURN mycat_seq_currval(seq_name);  
END
;;
DELIMITER ;
​
​
DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), VALUE INTEGER) 
RETURNS VARCHAR(64) CHARSET utf8DETERMINISTIC
BEGIN UPDATE MYCAT_SEQUENCE  SET current_value = VALUE  WHERE NAME = seq_name;  RETURN mycat_seq_currval(seq_name);  
END
;;
DELIMITER ;

配置sequence_db_conf.properties文件:

# sequence stored in datanode
# 索引名字必须和数据库表中村的索引名一致
GLOBAL=dn1
COMPANY=dn1
CUSTOMER=dn1
ORDERS=dn1

重启:

重启mycat

测试:

SELECT next value for MYCATSEQ_GLOBAL;
SELECT next value for MYCATSEQ_COMPANY;
​
​
insert into tb_order(id,clientid,goods_id,shop_id,create_time,shard_date)
values(next value for MYCATSEQ_GLOBAL,19,10001,101,now(),'2022-03-22');

5.4 本地时间戳方式

<property name="sequnceHandlerType">2</property>

重启:

重启mycat

测试:

insert into tb_order(id,clientid,goods_id,shop_id,create_time,shard_date)
values(next value for MYCATSEQ_GLOBAL,19,10001,101,now(),'2024-06-21');

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53180.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“Interface 和 Type 区别”深度解析

“Interface 和 Type 区别”深度解析 文章目录 一、Interface 和 Type 是什么二、如何使用 Interface 和 Type1. 定义 Interface2. 定义 Type3. 使用 Interface 和 Type4. 区别与联系 三、Interface 和 Type 二者有哪些区别&#xff0c;分别在哪些场景使用1. 区别2. 场景 四、扩…

深入解析反射型 XSS 与存储型 XSS:原理、危害与防范

在网络安全领域&#xff0c;跨站脚本攻击&#xff08;XSS&#xff09;是一种常见的安全漏洞。XSS 攻击可以分为反射型 XSS 和存储型 XSS 两种类型。本文将详细介绍这两种类型的 XSS 攻击的原理、危害和防范措施。 一、反射型 XSS 1、原理 反射型 XSS 攻击也称为非持久性 XSS …

数据丢失要怎么处理,助你一键恢复数据

你平常会用优盘来传输资料吗&#xff1f;如果你也出现过优盘因为病毒或者误操作等原因引起了数据丢失的情况那就继续往下看吧。这篇文章带你了解u盘格式化后数据能恢复吗&#xff0c;带你了解可操作的工具。 1.福昕恢复数据 链接直达&#xff1a;https://www.pdf365.cn/foxit…

集成电路学习:什么是RTOS实时操作系统

RTOS&#xff1a;实时操作系统 RTOS&#xff0c;全称Real Time Operating System&#xff0c;即实时操作系统&#xff0c;是一种专为满足实时控制需求而设计的操作系统。它能够在外部事件或数据产生时&#xff0c;以足够快的速度进行处理&#xff0c;并在规定的时间内控制生产过…

2024国赛数学建模-模拟火算法(MATLAB 实现)

模拟退火算法 1.1 算法原理 模拟退火算法的基本思想是从一给定解开始 ,从邻域 中随机产生另一个解 ,接受 Metropolis准则允许目标函数在 有限范围内变坏 ,它由一控制参数 t决定 ,其作用类似于物 理过程中的温度 T,对于控制参数的每一取值 ,算法持续进 行“产生 —判断 —接受…

vscode中暂存块功能不能用了

vscode中暂存文件修改可以按每一处暂存&#xff0c;而不用一次暂存整个文件的修改&#xff0c;今天发现这个功能不能用了&#xff0c;不知道啥原因&#xff0c;记录一下。

Android 存储之 SharedPreferences 框架体系编码模板

一、SharedPreferences 框架体系 1、SharedPreferences 基本介绍 SharedPreferences 是 Android 的一个轻量级存储工具&#xff0c;它采用 key - value 的键值对方式进行存储 它允许保存和读取应用中的基本数据类型&#xff0c;例如&#xff0c;String、int、float、boolean …

JavaWeb案例

环境搭建 先创建好数据库&#xff0c;建表并插入数据 create database talis; use talis;-- 部门管理 create table dept(id int unsigned primary key auto_increment comment 主键ID,name varchar(10) not null unique comment 部门名称,create_time datetime not null com…

QT QGraphicsView实现预览图片显示缩略图功能

QT QGraphicsView实现预览图片显示缩略图功能QT creator Qt5.15.2 头文件&#xff1a; #ifndef TGRAPHICSVIEW_H #define TGRAPHICSVIEW_H#include <QGraphicsView> #include <QMainWindow> #include <QObject> #include <QWidget>class TGraphicsVie…

TCP的传输速度

如何确定TCP最大传输速度&#xff1f; TCP 的传输速度&#xff0c;受限于发送窗⼝&#xff0c;接收窗⼝以及⽹络设备传输能⼒。 其中&#xff0c;窗⼝⼤⼩由内核缓冲区⼤⼩决定。如果缓冲区与⽹络传输能⼒匹配&#xff0c;那么缓冲区的利⽤率就达到了最⼤化。 如何计算网络传…

vue transition组件

可能不生效的几个注意点 选择器的优先级谨慎合并样式 显示三阶段和隐藏三阶段的class名 1、vue2中显示的初始阶段类名是&#xff1a;v-enter&#xff1b;隐藏的初始阶段类名是&#xff1a;v-leave2、v-enter-active、v-leave-active这两个 class 可以被用来定义动画的持续时间…

设计模式1:C#开发中使用创建型的工厂模式和行为型的策略模式

一、接口设计的好处 三大好处&#xff1a;解耦、可复用、可扩展。 二、简单工厂模式 【三要素】能创建具体产品的工厂、抽象产品&#xff08;接口&#xff09;、具体产品 【基本用法】字符串>创建对象>调用其方法 // 产品接口 public interface IProduct {void Opera…

应用开发---VTK放大镜(区域放大)功能实现

VTK 医学图像处理---放大镜/区域放大功能 本博文主要内容为:实现放大镜的源代码;实现思路;具体代码说明。 目录 VTK 医学图像处理---放大镜/区域放大功能 简介: 1 放大镜源代码 1 wxInteractorStyleImage 类源代码 2 wxMagnifierAcotor类源代码 3 Magnifier.cpp 源…

Android 打开 GBK项目如何设置成UTF-8

1.标题 今天打开一个eclipse老项目&#xff0c;编码格式为GBK&#xff0c;Android studio导入项目报错&#xff0c;本人想到一个方案就是批量修改文件格式从 GBK到 UTF-8&#xff0c;这样可以一键解决问题 2.开发脚本 使用前请备份代码 使用前请备份代码 使用前请备份代码…

NLP从零开始------文本中阶处理之序列到序列模型(完整版)

1. 序列到序列模型简介 序列到序列( sequence to sequence, seq2seq) 是指输入和输出各为一个序列(如一句话) 的任务。本节将输入序列称作源序列&#xff0c;输出序列称作目标序列。序列到序列有非常多的重要应用&#xff0c; 其中最有名的是机器翻译( machine translation), 机…

WebRTC协议下的视频汇聚融合技术:EasyCVR视频技术构建高效视频交互体验

视频汇聚融合技术是指将来自不同源、不同格式、不同网络环境的视频流进行集中处理、整合和展示的技术。随着视频监控、远程会议、在线教育、直播娱乐等领域的快速发展&#xff0c;视频数据的规模急剧增长&#xff0c;对视频处理能力和效率提出了更高要求。视频汇聚融合技术通过…

思科IP访问控制列表3

#网络安全技术实现# #任务三扩展访问控制列表的控制3# #1配置计算机的IP 地址、子网掩码和网关 #2配置Switch-A的主机名称&#xff0c;创建vlan 10,20,30,并将Fa0/1划入vlan 10&#xff0c;Fa0/2划入vlan 20&#xff0c;G0/1划入vlan 30 Switch(config)#hostname Switch-A S…

「OC」iOS事件处理流程

「OC」初识iOS事件处理流程 文章目录 「OC」初识iOS事件处理流程触摸事件触摸事件的响应周期事件 响应者UIEventUITouchUIResponder 触摸流程系统响应阶段APP响应阶段寻找最佳响应者 构成响应链 寻找最佳响应者和响应链的区别总结参考资料 触摸事件 iOS的事件有好几种&#xf…

DriveLM的baseline复现

DriveLM是一篇很有意思的工作&#xff0c;把自动驾驶跟MLLM结合到一起了&#xff0c;实现端到端的感知or决策规划。 Repo&#xff1a;https://github.com/OpenDriveLab/DriveLM 该工作是基于nuScenes数据集做的&#xff0c;官方paper里给出了数据的具体构建方式&#xff0c;感…

SpringBoot依赖之Spring Boot DevTools热部署开发增效工具

摘要&#xff1a;Spring项目又大又重&#xff0c;依赖多&#xff0c;编译启动慢&#xff0c;怎么提高研发效率呢&#xff1f;方法之一热部署&#xff01; 概念 Spring Boot DevTools 依赖名称: Spring Boot DevTools功能描述: Provides fast application restarts, LiveRelo…