首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 利用 REPLACE INTO 與 LAST_INSERT_ID() 實現全局唯一 ID 生成器

     編輯:MySQL 資料庫相關知識

前言

分庫分表架構下,需要跨分片的全局唯一 ID。MySQL 提供 REPLACE INTO 與 LAST_INSERT_ID() 擴展功能,可輕鬆構建高效能的全局 ID 生成器。本文介紹兩種實作模式:單序列模式與多業務共享序列模式。

方案一:單表單序列模式(Flicker 方案)

建表

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;

獲取 ID

REPLACE INTO `tickets64` (`stub`) VALUES ('a');
SELECT LAST_INSERT_ID();

原理

  • 首次執行:插入新行,id=1
  • 再次執行:stub='a' 衝突 → 刪除舊行 → 重新插入 → id=2
  • 表永遠只保留一行,id 持續遞增

方案二:多業務共享序列表(推薦)

建表

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');

獲取指定業務 ID(如 photos)

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)
  • 後續執行:觸發 UPDATE,id 遞增並返回新值
  • 可接受從 0 開始,或預先 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 事務安全、易擴展需維護序列表多業務分庫分表
雙主奇偶高可用、無單點資源佔用雙倍核心業務、強一致性要求
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved