利用 MySQL REPLACE INTO 特性:唯一鍵衝突時先刪除舊行再插入新行。配合 LAST_INSERT_ID() 獲取自增值,實現無鎖、高效能的 ID 生成。
CREATE TABLE `tickets64` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`stub` CHAR(1) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `stub` (`stub`)
) ENGINE=MyISAM;
-- 獲取 ID
REPLACE INTO `tickets64` (`stub`) VALUES ('a');
SELECT LAST_INSERT_ID();
執行後表永遠只有 1 行,id 持續遞增:1, 2, 3... 原子操作,無並發衝突。
CREATE TABLE `sequence` (
`name` VARCHAR(50) NOT NULL,
`id` BIGINT UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`name`)
) ENGINE=InnoDB;
-- 初始化
INSERT INTO `sequence` (`name`) VALUES ('users'), ('photos'), ('albums'), ('comments');
關鍵差異:id 非自增、非主鍵,name 為主鍵。
UPDATE `sequence` SET `id` = LAST_INSERT_ID(`id` + 1) WHERE `name` = 'photos'; SELECT LAST_INSERT_ID();
LAST_INSERT_ID(expr) 將函數返回值設為 exprINSERT INTO `sequence` (`name`) VALUES('new_business')
ON DUPLICATE KEY UPDATE `id` = LAST_INSERT_ID(`id` + 1);
SELECT LAST_INSERT_ID();
id=0,LAST_INSERT_ID() 返回 0(無自增欄位)參考 Flicker 奇偶數思路,擴展至 N 節點:
i(0-based 連續)auto_increment_increment = N(步長)優於 Flicker:不限於 2 節點、InnoDB 支援事務、單表管理所有序列。
這一方案不依賴外部中間件、程式碼極簡、擴展靈活,適合中小規模、已有 MySQL 基礎設施的系統。大規模高並發建議遷移至 Snowflake 等無協調演算法。