分库主键设计-Mysql

常见的两种方案,遍及网络:

第一种:
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

相关文章
相关标签/搜索