資料庫自增主鍵可能產生的問題

weixin_33816946發表於2016-04-14

在MySQL中經常會配置自增長屬性的欄位作為主鍵,特別是使用InnoDB儲存引擎,

因為InnoDB的聚集索引的特性,使用自增長屬性的欄位當主鍵效能更好,但是使用自增主鍵也可能會帶來一些問題。
舉個例子,使用自增主鍵對資料庫做分庫分表,可能出現一些諸如主鍵重複等的問題,或者在資料庫匯入的時候,可能會因為主鍵出現一些問題。

主要業務表的主鍵應該配置一個合理的策略,儘量避免自增AUTO_INCREMENT。

針對主鍵自增可能產生的問題,下面這兩篇文章有相關的討論:

INNODB自增主鍵的一些問題
mysql自增列導致主鍵重複問題分析

 

針對主鍵增長方式的解決方案

來自知乎問題-高併發網站如何解決資料庫主鍵自增的時候出現重複?

(1)設定主鍵自增為何不可取
這樣的話,資料庫本身是單點,不可拆庫,因為id會重複。

(2)依賴資料庫自增機制達到全域性ID唯一
使用如下語句:
REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
這樣可以保證全域性ID唯一,但這個Tickets64表依舊是個單點。

(3)依賴資料庫自增機制達到全域性ID唯一併消除單點
在2的基礎上,部署兩個(多個)資料庫例項,
設定自增步長為2(多個則為例項數),即auto-increment-increment = 2
設定auto-increment-offset分別為1,2.....
這樣第一臺資料庫伺服器的自增id為 1 3 5 7 9
第二臺為2 4 6 8 10

(4)解決每次請求全域性ID都讀庫寫庫壓力過大的問題
比如第一次啟動業務服務,會請求一個唯一id為3559
如果是2、3的方法,則id為3559,這樣每次都請求資料庫,對資料庫壓力比較大
可以用3559 * 65536(舉個例子,並不一定是65536)+ 記憶體自增變數來作為id
當記憶體自增變數到達65535時,從資料庫重新獲取一個自增id
這樣即使有多臺業務伺服器,id也不會重複:
第一臺 3559 * 65536 + 1,2,3.....65535
第二臺 3560 * 65536 + 1,2,3.....65535
然後第一臺到65535了,換一個資料庫自增id,這時候可能是3561 * 65536 + 1,2,3....

 

相關文章