常見的兩種方案,遍及網絡:
第一種:
replace方案,mysql解釋:REPLACE的運行與INSERT很相像。只有一點除外,若是表中的一箇舊記錄與一個用於PRIMARY KEY或一個UNIQUE索引的新記錄具備相同的值,則在新記錄被插入以前,舊記錄被刪除。html
CREATE TABLE `user_id_seq` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `stub` varchar(3) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `stub` (`stub`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 REPLACE INTO user_id_seq(stub) VALUES ('a'); select last_insert_id();
這種方案通常一個表對應一個類型的主鍵,簡單明瞭,一個表對應一個業務的seq。可是在高併發的狀況下很容易致使mysql死鎖。
第二種:java
CREATE TABLE `sequence` ( `name` varchar(50) NOT NULL, `id` bigint(20) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 INSERT INTO `sequence` (`name`) VALUES('users'); update sequence set id=last_insert_id(id+1) where name = 'users'; select last_insert_id();
這種方案能夠一個表支持多個業務的seq需求,可是太多的業務對這一個表頻繁操做,若是某個業務出現鎖表,就會致使其餘業務沒法進行。mysql
第三種:spring
若是是java的項目,可使用spring框架的MySQLMaxValueIncrementer解決,在mysql上實現原理同第二種,只是在業務層加了一段本地緩存,對於seq請求很高的業務能夠較好的保障。
以上三種方案的都關係到mysql的last_insert_id()這個功能,其實關鍵點也就是這個last_insert_id()使咱們能夠經過mysql實現惟一seq的設計。
mysql中對它的解釋:【對於LAST_INSERT_ID(),最近生成的ID是在服務器上按鏈接維護的。它不會被另外一個客戶端改變。即便用non-magic值(即非Null非0值)更新了另外一個AUTO_INCREMENT列,也不會更改它。】
mysql如何得到上次插入行的惟一ID
http://dev.mysql.com/doc/refman/5.1/zh/apis.html#getting-unique-id
這樣無論咱們如何設計,只要保證select last_insert_id();以前的操做是一個鏈接完成的原子操做,咱們就能從返回值中獲得惟一的last_insert_id。sql