常见的两种方案,遍及网络:
第一种:
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