currval()/nextval() 封裝邏輯;DROP TABLE IF EXISTS sequence;
CREATE TABLE sequence (
seq_name VARCHAR(50) NOT NULL COMMENT '序列名',
current_val INT NOT NULL COMMENT '當前值',
increment_val INT NOT NULL DEFAULT 1 COMMENT '步長',
PRIMARY KEY (seq_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO sequence VALUES ('seq_test1_num1', 0, 1);
INSERT INTO sequence VALUES ('seq_test1_num2', 0, 2);
CREATE FUNCTION currval(v_seq_name VARCHAR(50)) RETURNS INT
BEGIN
DECLARE value INT DEFAULT 0;
SELECT current_val INTO value FROM sequence WHERE seq_name = v_seq_name;
RETURN value;
END;
CREATE FUNCTION nextval(v_seq_name VARCHAR(50)) RETURNS INT
BEGIN
UPDATE sequence SET current_val = current_val + increment_val WHERE seq_name = v_seq_name;
RETURN currval(v_seq_name);
END;
SELECT currval('seq_test1_num1'); -- 0
SELECT nextval('seq_test1_num1'); -- 1
SELECT nextval('seq_test1_num2'); -- 2
DROP TABLE IF EXISTS test1;
CREATE TABLE test1 (
name VARCHAR(255) NOT NULL,
value DOUBLE(255,0) DEFAULT NULL,
num1 INT(11) DEFAULT NULL,
num2 INT(11) DEFAULT NULL,
PRIMARY KEY (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TRIGGER TRI_test1_num1 BEFORE INSERT ON test1
FOR EACH ROW
BEGIN
SET NEW.num1 = nextval('seq_test1_num1');
SET NEW.num2 = nextval('seq_test1_num2');
END;
INSERT INTO test1 (name, value) VALUES ('1', 111), ('2', 222), ('3', 333), ('4', 444);
SELECT * FROM test1;
/*
+------+-------+------+------+
| name | value | num1 | num2 |
+------+-------+------+------+
| 1 | 111 | 1 | 2 |
| 2 | 222 | 2 | 4 |
| 3 | 333 | 3 | 6 |
| 4 | 444 | 4 | 8 |
+------+-------+------+------+
*/
| 能力 | 實現方式 |
|---|---|
| 單表多自增列 | 不同序列名映射不同列 |
| 自定義步長 | increment_val 列控制 |
| 跨表共享序列 | 多表觸發器調用同一 nextval() |
| 事務安全 | InnoDB 行鎖保證序列不重不漏 |
| 重啟持久化 | current_val 持久化存儲 |
單行更新成熱點時,採用「批次預取」:
CREATE FUNCTION nextval_batch(v_seq_name VARCHAR(50), batch_size INT) RETURNS INT
BEGIN
UPDATE sequence SET current_val = current_val + increment_val * batch_size WHERE seq_name = v_seq_name;
RETURN currval(v_seq_name) - increment_val * (batch_size - 1); -- 返回批次起始值
END;
應用端緩存批次範圍,本地分配,耗盡再取下一批,極大降低序列表寫入壓力。