MySQL 模拟自增序列(Sequence)实现方案

江屿
江屿
发布时间:2026-10-13| 6人浏览过
原创

由于 MySQL 原生不支持像 Oracle 那样的 Sequence,在需要生成全局唯一流水号或多表共享自增标识时,需通过建立专用管理表和自定义存储函数来模拟实现。

问题背景与准备条件

在多项目开发或接口设计中,常遇到以下场景:

  • 需要发送 int 或 long 类型的流水号。
  • 在高并发或多线程模式下使用系统时间戳作为主键,极小概率下会出现重复值。
  • 业务上要求不使用 MySQL 原生自增列的限制(如单表单字段限制),而需要一个独立于具体业务表的自增标识源。

为解决上述问题,我们通过一张名为 sequence 的表配合三个辅助函数来实现序列功能。

第1步:创建 Sequence 管理表

此步骤的核心目的是建立一个专门用于存放序列名称、当前值和递增幅度的数据表。为了保证性能和避免锁表竞争,建议配置为 InnoDB 引擎。

操作入口:数据库管理工具或命令行客户端
执行动作:运行建表 SQL。
注意:若环境已存在同名表,请先执行 DROP TABLE IF EXISTS sequence; 以防冲突。

-- 基础版(INT类型)
DROP TABLE IF EXISTS sequence; 
CREATE TABLE sequence ( 
     name VARCHAR(50) NOT NULL, 
     current_value INT NOT NULL, 
     increment INT NOT NULL DEFAULT 1, 
     PRIMARY KEY (name) 
) ENGINE=InnoDB;

如需支持更大范围的数值且兼容不同大小写,可采用以下优化后的版本:

CREATE TABLE sequence (
   name       VARCHAR(50) NOT NULL,
   current_value   BIGINT UNSIGNED NOT NULL DEFAULT 0,
   increment     INT NOT NULL DEFAULT 1,
   PRIMARY KEY (name)
) ENGINE=InnoDB;

第2步:定义核心函数

为了实现序列的功能,必须配合三个函数使用:currval 获取当前值,nextval 获取并递增下一个值,以及 setval 重置指定序列的值。

第2.1步:创建 currval 函数

目的:查询指定名称序列的当前值。
参数:seq_name (VARCHAR) 序列名称。

DELIMITER $ 
CREATE FUNCTION currval (seq_name VARCHAR(50)) 
     RETURNS INTEGER 
     LANGUAGE SQL 
     DETERMINISTIC 
     CONTAINS SQL 
     SQL SECURITY DEFINER 
BEGIN 
     DECLARE value INTEGER;
     SET value = 0; 
     SELECT current_value INTO value 
          FROM sequence 
          WHERE name = seq_name; 
     RETURN value; 
END
$ 
DELIMITER ; 

对于 BIGINT 版本的表,函数如下:

CREATE FUNCTION currval(seq_name VARCHAR(50)) 
RETURNS BIGINT
BEGIN
     DECLARE value BIGINT;
     SELECT current_value INTO value
     FROM sequence
     WHERE upper(name) = upper(seq_name);
     RETURN value;
END;

第2.2步:创建 nextval 函数

目的:原子性地更新增量并返回新的序列值。这是生成流水号时应调用的主要函数。
参数:seq_name (VARCHAR) 序列名称。

DELIMITER $ 
CREATE FUNCTION nextval (seq_name VARCHAR(50)) 
     RETURNS INTEGER 
     LANGUAGE SQL 
     DETERMINISTIC 
     CONTAINS SQL 
     SQL SECURITY DEFINER 
BEGIN 
     UPDATE sequence 
          SET current_value = current_value + increment 
          WHERE name = seq_name; 
     RETURN currval(seq_name); 
END
$ 
DELIMITER ; 

第2.3步:创建 setval 函数

目的:手动修改指定序列的起始值或重置计数。
参数:seq_name (VARCHAR),value (INTEGER 或 BIGINT)。

DELIMITER $ 
CREATE FUNCTION setval (seq_name VARCHAR(50), value INTEGER) 
     RETURNS INTEGER 
     LANGUAGE SQL 
     DETERMINISTIC 
     CONTAINS SQL 
     SQL SECURITY DEFINER 
BEGIN 
     UPDATE sequence 
          SET current_value = value 
          WHERE name = seq_name; 
     RETURN currval(seq_name); 
END
$ 
DELIMITER ; 

第3步:测试与验证

完成以上配置后,即可通过 SQL 语句对序列进行初始化、读取和递增加操。

  1. 插入/初始化序列:添加一个名为 'TestSeq' 的序列,初始值为 0,每次递增 1。
    INSERT INTO sequence VALUES ('TestSeq', 0, 1);
  2. 重置值:将 'TestSeq' 的当前值设置为 10。
    SELECT SETVAL('TestSeq', 10);
  3. 查看当前值:输出应为 10。
    SELECT CURRVAL('TestSeq');
  4. 获取下一个值:该函数会先加 1 再返回,因此再次查看当前值或执行此条,预期结果变为 11。
    SELECT NEXTVAL('TestSeq');

以下是基于 BIGINT 版本的完整演示:

mysql> insert into sequence set name='myseq';
mysql> select * from sequence;
-- 输出: | myseq | 0 | 1 |

mysql> select nextval('myseq');
-- 输出: | 1 |

第4步:Java 应用层集成

在实际项目中,可以在 Java 代码中直接拼接 SQL 语句来获取流水号。该方法通过 JDBC 驱动执行 SELECT NEXTVAL(...) 并捕获返回值。

public void testGetSequence() {
  Connection conn = DataSourceUtil.getConnection(); // 替换为你的数据源获取方式
  String sql = "SELECT NEXTVAL('TestSeq');"; 
  PreparedStatement ptmt = null; 
  ResultSet rs = null; 
  try { 
    ptmt = conn.prepareStatement(sql); 
    rs = ptmt.executeQuery(); 
    int count = 0; 
    while (rs.next()) { 
      count = rs.getInt(1); 
    } 
    System.out.println("Generated Sequence Value: " + count); 
  } catch (SQLException e) { 
    e.printStackTrace(); 
  } finally { 
    try { if(rs!=null) rs.close(); if(ptmt!=null) ptmt.close(); if(conn!=null) conn.close(); } catch (Exception ex) {}
  } 
}

补充说明:关于高并发性能与替代方案

性能考量:
使用数据库表+函数的方式利用了数据库事务的天然原子性,安全性较高。但在极高并发写入场景下,频繁的对同一行记录(`sequence` 表中的特定 `name`)进行读写会产生行级锁(Row Lock)。若发现成为瓶颈,可考虑以下策略:

  • 内存缓存法:利用 Redis 的 INCR 命令生成 ID,定期同步至数据库,适用于海量流水号需求。
  • 应用层分布式算法:如雪花算法(Snowflake),完全由程序逻辑保证全局唯一,减轻 DB 压力。

以上就是在 MySQL 数据库中创建实现自增序列(Sequence)教程的详细内容,更多关于如何在 MySQL 中高效处理高并发序列的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。