基于Mysql的Sequence实现方法
文件大小: 92k
源码售价: 10 个金币 积分规则     积分充值
资源说明:团队更换新框架。新的业务全部使用新的框架,甚至是新的数据库–Mysql。 这边之前一直是使用oracle,各种订单号、流水号、批次号啥的,都是直接使用oracle的sequence提供的数字序列号。现在数据库更换成Mysql了,显然以前的老方法不能适用了。 需要新写一个: •分布式场景使用 •满足一定的并发要求 找了一些相关的资料,发现mysql这方面的实现,原理都是一条数据库记录,不断update它的值。然后大部分的实现方案,都用到了函数。 贴一下网上的代码: 基于mysql函数实现 表结构 CREATE TABLE `t_sequence` ( `sequence_name` varch 在Oracle数据库中,Sequence是一种非常方便的工具,用于生成唯一的序列号,常用于主键或者流水号等场景。然而,MySQL数据库本身并不直接支持类似Oracle的Sequence功能。当从Oracle迁移到MySQL时,我们需要寻找替代的实现方式。本文将探讨如何在MySQL中模拟Sequence,并考虑在分布式场景下满足一定的并发要求。 一种常见的实现方式是通过创建一个包含序列名称和当前值的表,例如`t_sequence`,并使用自定义的函数(如`nextval`)来更新并返回序列的下一个值。以下是一个简单的表结构和函数定义: ```sql CREATE TABLE `t_sequence` ( `sequence_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '序列名称', `value` int(11) NULL DEFAULT NULL COMMENT '当前值', PRIMARY KEY (`sequence_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=COMPACT; CREATE DEFINER = `root`@`localhost` FUNCTION `nextval`(sequence_name varchar(64)) RETURNS int(11) BEGIN declare current integer; set current = 0; update t_sequence t set t.value = t.value + 1 where t.sequence_name = sequence_name; select t.value into current from t_sequence t where t.sequence_name = sequence_name; return current; END; ``` 这种实现方式在并发场景下可能会出现问题,因为多个请求可能同时尝试更新同一个序列,导致数据不一致。为了解决这个问题,我们可以引入乐观锁的概念,通过版本号或时间戳来确保更新的顺序。另外,可以优化设计,让每个请求获取一段序列值,而不是单个值,比如每次获取100个序列号,存储在本地缓存中。当缓存中的序列用完后,再从数据库中重新获取。这样可以减少数据库的交互次数,提高性能。 以下是一个基于Java实现的示例,使用了乐观锁和本地缓存策略: 创建一个存储序列信息的表`t_pub_sequence`,包含序列名称、当前值、最小值、最大值、每次取值的数量以及创建和修改时间: ```sql CREATE TABLE `t_pub_sequence` ( `SEQ_NAME` varchar(128) CHARACTER SET utf8 NOT NULL COMMENT '序列名称', `SEQ_VALUE` bigint(20) NOT NULL COMMENT '目前序列值', `MIN_VALUE` bigint(20) NOT NULL COMMENT '最小值', `MAX_VALUE` bigint(20) NOT NULL COMMENT '最大值', `STEP` bigint(20) NOT NULL COMMENT '每次取值的数量', `TM_CREATE` datetime NOT NULL COMMENT '创建时间', `TM_SMP` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`SEQ_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='流水号生成表'; ``` 接着,定义一个`MysqlSequence`接口,用于获取序列号: ```java public interface MysqlSequence { String nextVal(String seqName); } ``` 然后,实现`MysqlSequence`接口的类,例如`MysqlSequenceImpl`,它负责从数据库中获取序列值并缓存一部分在内存中: ```java public class MysqlSequenceImpl implements MysqlSequence { // 实现获取序列号的方法,包括从数据库读取、更新、缓存等逻辑 ... } ``` 在`MysqlSequenceImpl`中,我们可以定义一个`SequenceRange`类来表示缓存的序列区间,以便在本地使用: ```java public class SequenceRange { // 包含序列区间的属性和方法,如getMinValue, getMaxValue等 ... } ``` 通过这种方式,我们可以利用MySQL数据库配合Java代码实现类似于Oracle Sequence的功能,同时适应分布式场景,保证并发安全。需要注意的是,这种方法可能需要根据实际的并发量和性能需求进行调整,例如调整每次获取的序列段大小,或者优化数据库查询和更新操作。此外,还可以考虑使用分布式ID生成器,如Twitter的Snowflake算法,或者阿里巴巴的分布式ID生成服务——Seata的ID Generator,以进一步提升性能和扩展性。
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。