AliSQL提供了Sequence Engine,簡化擷取序列值的複雜度。
Sequence Engine介紹
在持久化資料庫系統中,無論是單節點中的業務主鍵,還是分布式系統中的全域唯一值,亦或是多系統中的等冪控制,單調遞增的唯一值是常見的需求。不同的資料庫系統有不同的實現方法,例如MySQL提供的AUTO_INCREMENT,Oracle、SQL Server提供的SEQUENCE。
在MySQL資料庫中,如果業務希望封裝唯一值,例如增加日期、使用者等資訊,使用AUTO_INCREMENT的方法會帶來很大不便,在實際的系統設計中,也存在不同的折中方法:
序列值由Application或者Proxy來產生,不過弊端很明顯,狀態帶到應用端會增加擴容和縮容的複雜度。
序列值由資料庫通過類比的表來產生,但需要中介軟體來封裝和簡化擷取唯一值的邏輯。
AliSQL提供了Sequence Engine,通過引擎的設計方法,儘可能地相容其他資料庫的使用方法,簡化擷取序列值複雜度。
Sequence Engine實現了MySQL儲存引擎的設計介面,但底層的資料仍然使用現有的儲存引擎,例如InnoDB或者MyISAM來儲存持久化資料,相容現有的第三方工具(例如Xtrabackup),所以Sequence Engine僅僅是一個邏輯引擎。
Sequence Engine通過Sequence Handler介面訪問Sequence對象,實現NEXTVAL的滾動、緩衝的管理等,最後透傳給底層的基表資料引擎,實現最終的資料訪問。
前提條件
執行個體版本如下:
RDS MySQL 8.0(核心小版本為20190816及以上)
RDS MySQL 5.7(核心小版本為20210430及以上)
RDS MySQL 5.6(核心小版本為20170901及以上)
執行個體系列不能是三節點企業系列。
使用限制
Sequence不支援子查詢和join查詢。
可以使用
SHOW CREATE TABLE
來訪問Sequence結構。不支援建表的時候指定Sequence引擎,Sequence表只能通過建立Sequence的文法來建立。
建立Sequence
建立Sequence語句如下:
CREATE SEQUENCE [IF NOT EXISTS] <資料庫名>.<Sequence名稱>
[START WITH <constant>]
[MINVALUE <constant>]
[MAXVALUE <constant>]
[INCREMENT BY <constant>]
[CACHE <constant> | NOCACHE]
[CYCLE | NOCYCLE]
;
方括弧([])中的內容非必填。
參數說明如下。
參數 | 說明 |
START WITH | Sequence的起始值。 |
MINVALUE | Sequence的最小值。 |
MAXVALUE | Sequence的最大值。 說明 如果有參數NOCYCLE,到達最大值後會報如下錯誤:
|
INCREMENT BY | Sequence的步長。 |
CACHE/NOCACHE | 緩衝的大小,為了效能考慮,可以設定較大的緩衝,但如果遇到執行個體重啟,緩衝內的值會丟失。 |
CYCLE/NOCYCLE | 表示Sequence如果用完了後,是否允許從MINVALUE重新開始。取值:
|
樣本:
create sequence s
start with 1
minvalue 1
maxvalue 9999999
increment by 1
cache 20
cycle;
為了相容MySQL Dump的備份方式,您也可以使用另外一種建立Sequence的方法,即建立Sequence表並插入一行初始記錄。樣本如下:
CREATE TABLE schema.sequence_name ( `currval` bigint(21) NOT NULL COMMENT 'current value',
`nextval` bigint(21) NOT NULL COMMENT 'next value',
`minvalue` bigint(21) NOT NULL COMMENT 'min value',
`maxvalue` bigint(21) NOT NULL COMMENT 'max value',
`start` bigint(21) NOT NULL COMMENT 'start value',
`increment` bigint(21) NOT NULL COMMENT 'increment value',
`cache` bigint(21) NOT NULL COMMENT 'cache size',
`cycle` bigint(21) NOT NULL COMMENT 'cycle state',
`round` bigint(21) NOT NULL COMMENT 'already how many round'
) ENGINE=Sequence DEFAULT CHARSET=latin1;
INSERT INTO schema.sequence_name VALUES(0,0,1,9223372036854775807,1,1,10000,1,0);
COMMIT;
Sequence表介紹
由於Sequence是通過真正的引擎表來儲存的,所以通過查詢建立語句看到仍然是預設的引擎表。樣本如下:
SHOW CREATE TABLE schema.sequence_name;
CREATE TABLE schema.sequence_name (
`currval` bigint(21) NOT NULL COMMENT 'current value',
`nextval` bigint(21) NOT NULL COMMENT 'next value',
`minvalue` bigint(21) NOT NULL COMMENT 'min value',
`maxvalue` bigint(21) NOT NULL COMMENT 'max value',
`start` bigint(21) NOT NULL COMMENT 'start value',
`increment` bigint(21) NOT NULL COMMENT 'increment value',
`cache` bigint(21) NOT NULL COMMENT 'cache size',
`cycle` bigint(21) NOT NULL COMMENT 'cycle state',
`round` bigint(21) NOT NULL COMMENT 'already how many round'
) ENGINE=Sequence DEFAULT CHARSET=latin1
查詢文法
Sequence支援的查詢文法如下:
SELECT nextval(<Sequence名稱>),currval(<Sequence名稱>) FROM <Sequence名稱>;
說明適用於MySQL 8.0、MySQL 5.7。
SELECT <Sequence名稱>.currval, <Sequence名稱>.nextval FROM dual;
說明適用於MySQL 8.0、MySQL 5.7、MySQL 5.6。
樣本:
mysql> SELECT test.currval, test.nextval from dual;
+--------------+--------------+
| test.currval | test.nextval |
+--------------+--------------+
| 24 | 25 |
+--------------+--------------+
1 row in set (0.03 sec)
新建立的Sequence需要先調用一次該Sequence的NEXTVAL才能正常進行查詢,否則會報Sequence 'xxx' is not yet defined in current session
錯誤。
NEXTVAL調用樣本:
SELECT <Sequence名稱>.nextval FROM dual;