需求:接口要求 int 類型流水號,多線程下時間戳可能重複,UUID 過長,需類 Oracle SEQUENCE 的單調遞增整數。
CREATE TABLE sequence ( name VARCHAR(50) NOT NULL PRIMARY KEY, current_value BIGINT UNSIGNED NOT NULL DEFAULT 0, increment INT NOT NULL DEFAULT 1 ) ENGINE=InnoDB;
currval(seq_name)DELIMITER $ CREATE FUNCTION currval(seq_name VARCHAR(50)) RETURNS BIGINT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER BEGIN DECLARE value BIGINT DEFAULT 0; SELECT current_value INTO value FROM sequence WHERE name = seq_name; RETURN value; END $ DELIMITER ;
nextval(seq_name)(核心)DELIMITER $ CREATE FUNCTION nextval(seq_name VARCHAR(50)) RETURNS BIGINT 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 ;
setval(seq_name, value)DELIMITER $ CREATE FUNCTION setval(seq_name VARCHAR(50), value BIGINT) RETURNS BIGINT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER BEGIN UPDATE sequence SET current_value = value WHERE name = seq_name; RETURN currval(seq_name); END $ DELIMITER ;
public class SequenceGenerator {
private DataSource dataSource;
private String seqName;
public SequenceGenerator(DataSource ds, String seqName) {
this.dataSource = ds;
this.seqName = seqName;
}
public long nextValue() {
String sql = "SELECT nextval(?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, seqName);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) return rs.getLong(1);
throw new IllegalStateException("Sequence not found: " + seqName);
}
} catch (SQLException e) {
throw new RuntimeException("Get sequence failed", e);
}
}
}
// 使用
SequenceGenerator orderSeq = new SequenceGenerator(dataSource, "OrderSeq");
long orderNo = orderSeq.nextValue(); // 線程安全,數據庫層面串行化
-- 修改管理表增加緩存字段 ALTER TABLE sequence ADD cache_size INT DEFAULT 100; ALTER TABLE sequence ADD cached_max BIGINT DEFAULT 0; -- nextval 邏輯優化: -- 1. 若 current_value < cached_max:直接 current_value++ 返回(無 UPDATE) -- 2. 否則:cached_max = current_value + cache_size; UPDATE ...; 返回 current_value++
應用層同樣可實現:批量獲取 100 個號段到內存,用完再取。
CREATE SEQUENCE order_seq START WITH 1 INCREMENT BY 1 CACHE 100; SELECT NEXT VALUE FOR order_seq; -- 獲取下一值 SELECT LAST_VALUE FROM order_seq; -- 當前值
原生 Sequence 效能更高、語法標準、支援緩存、循環、權限控制。**MySQL 8.0+ 專案優先使用原生**。
| 特性 | AUTO_INCREMENT | Sequence |
|---|---|---|
| 作用域 | 單表單列 | 全域/多表共用 |
| 類型限制 | 整數類型 | 任意整數類型 |
| 業務解耦 | 綁定表結構 | 獨立對象 |
| 批量預取 | 不支援 | 支援 (CACHE) |
| 重置/跳號 | 麻煩 | 靈活 (setval) |
sequence 表 + nextval/currval/setval 函數模擬 Oracle SequenceCREATE SEQUENCE**,標準、高效、免維護