分庫分表架構下,需要跨分片的全局唯一 ID。MySQL 提供 REPLACE INTO 與 LAST_INSERT_ID() 擴展功能,可輕鬆構建高效能的全局 ID 生成器。本文介紹兩種實作模式:單序列模式與多業務共享序列模式。
CREATE TABLE `tickets64` ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, `stub` CHAR(1) NOT NULL DEFAULT '', PRIMARY KEY (`id`), UNIQUE KEY `stub` (`stub`) ) ENGINE=MyISAM;
REPLACE INTO `tickets64` (`stub`) VALUES ('a');
SELECT LAST_INSERT_ID();
id=1stub='a' 衝突 → 刪除舊行 → 重新插入 → id=2id 持續遞增CREATE TABLE `sequence` ( `name` VARCHAR(50) NOT NULL, `id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY (`name`) ) ENGINE=InnoDB;
注意:id 非自增、非主鍵,主鍵為 name。
INSERT INTO `sequence` (`name`) VALUES ('users'), ('photos'), ('albums'), ('comments');
UPDATE `sequence` SET `id` = LAST_INSERT_ID(`id` + 1) WHERE `name` = 'photos'; SELECT LAST_INSERT_ID();
關鍵技巧:LAST_INSERT_ID(expr) 將表達式結果作為函數返回值,後續 SELECT LAST_INSERT_ID() 即可取得新 ID。
INSERT INTO `sequence` (`name`) VALUES('new_business')
ON DUPLICATE KEY UPDATE `id` = LAST_INSERT_ID(`id` + 1);
SELECT LAST_INSERT_ID();
id=0,返回 0(因未觸發 UPDATE)id 遞增並返回新值SET id=1參考 Flicker 架構,部署兩台 MySQL:
-- Server 1 auto_increment_increment = 2 auto_increment_offset = 1 -- Server 2 auto_increment_increment = 2 auto_increment_offset = 2
客戶端輪詢兩台服務獲取 ID,實現無單點、高可用的全局 ID 服務。擴展至 N 台同理,步長設為 N,偏移量 1~N。
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| 單表 REPLACE | 極簡、MyISAM 高效能 | 單點、僅支援單序列 | 單業務、低併發 |
| 共享序列表 | 多業務隔離、InnoDB 事務安全、易擴展 | 需維護序列表 | 多業務分庫分表 |
| 雙主奇偶 | 高可用、無單點 | 資源佔用雙倍 | 核心業務、強一致性要求 |