首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 分表後自增 ID 衝突解決方案:獨立 ID 表、Redis、隊列預分配三大模式

     編輯:MySQL 綜合教學

MySQL 分表後自增 ID 衝突解決方案:獨立 ID 表、Redis、隊列預分配三大模式

分表後,各表自增 ID 獨立遞增,全域唯一性失效。本文對比三種主流解決方案,並提供 PHP 實作範例,助你根據併發量與業務選型。

方案一:獨立 ID 產生表(資料庫層)

CREATE TABLE `create_id` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=MyISAM;

插入資料前先向此表寫入一筆空記錄,取得 LAST_INSERT_ID() 作為全域 ID:

function get_AI_ID() {
  $sql = "INSERT INTO create_id (id) VALUES ('')";
  $this->db->query($sql);
  return $this->db->insertID();
}

優缺點分析

優點缺點
實作簡單、ACID 保證、無額外元件高併發下 AUTO_INCREMENT 表鎖/行鎖成為瓶頸

InnoDB 自增鎖模式調優

innodb_autoinc_lock_mode = 0  -- Traditional:每次插入表鎖
innodb_autoinc_lock_mode = 1  -- Consecutive(預設):可預測筆數用批量鎖,否則表鎖
innodb_autoinc_lock_mode = 2  -- Interleaved:無鎖,來一個處理一個,併發最高

高併發建議設為 2,但可能導致自增值不連續(有間隙)。MyISAM 僅支援 Traditional 模式。

方案二:Redis 原子遞增(高效能、去中心化)

function get_next_autoincrement($timeout = 60) {
  // 分散式鎖防止並發初始化
  if (!get_lock("serial:lock", $timeout)) return 0;
  $id = $redis->incr("serial");
  if ($id > 1) { release_lock("serial:lock"); return $id; }
  // 首次初始化:從 DB 取得最大 ID
  $maxId = $db->query("SELECT MAX(id) FROM user_posts")->fetchColumn();
  $id = $maxId + 1;
  $redis->set("serial", $id);
  release_lock("serial:lock");
  return $id;
}

優點:極高併發效能、單機/叢集皆適用。缺點:引入 Redis 依賴、需處理網路故障與持久化一致性。

方案三:隊列預分配(號段模式,適合業務賦義 ID)

class IdQueue {
  private $redis;
  public function __construct() { $this->redis = new Redis(); $this->redis->connect('127.0.0.1', 6379); }
  public function pushBatch(array $ids) { foreach ($ids as $id) $this->redis->lPush('id_queue', $id); }
  public function pop() { return $this->redis->lPop('id_queue'); }
}

// 初始化:預生成 20 個 1000~4000 間的靚號
$ids = []; while (count($ids) < 20) { $n = rand(1000,4000); if (!in_array($n,$ids)) $ids[]=$n; }
$queue = new IdQueue(); $queue->pushBatch($ids);

// 業務使用
$id = $queue->pop();
if ($id) { $sql = "INSERT INTO user_posts(id,...) VALUES($id,...)"; }

優點:可規劃「靚號」銷售、ID 帶業務含義、DB 寫入零鎖競爭。缺點:需監控隊列長度自動補充、ID 耗盡風險。

選型建議

  • 中低併發、簡單專案:方案一 + innodb_autoinc_lock_mode=2
  • 高併發、微服務架構:方案二(Redis Cluster)
  • ID 需業務語義、營收變現:方案三(號段隊列)

避免直接使用分表後的各表自增 ID 作為全域主鍵,必須引入全域 ID 生成機制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved