基于MySql的扩展功能生成全局ID
本文利用MySQL的扩展功能REPLACEINTO来生成全局id,REPLACEINTO和INSERT的功能一样,但是当使用REPLACEINTO插入新数据行时,如果新插入的行的主键或唯一键(UNIQUEKey)已有的行重复时,已有的行会先被删除,然后再将新数据行插入(REPLACEINTO是原始操作)。
建立类似下面的表:
CREATETABLE`tickets64`( `id`bigint(20)unsignedNOTNULLauto_increment, `stub`char(1)NOTNULLdefault'', PRIMARYKEY(`id`), UNIQUEKEY`stub`(`stub`) )ENGINE=MyISAM;
当需要获得全局唯一ID时,执行下面的SQL语句:
REPLACEINTO`tickets64`(`stub`)VALUES('a'); SELECTLAST_INSERT_ID();
第一次执行这个语句后,ticket64表将包含以下数据:
+--------+------+
|id |stub|
+--------+------+
|1 | a|
+--------+------+
以后再次执行前面的语句,stub字段值为'a'的行已经存在,所以MySQL会先删除这一行,再插入。因此,第二次执行后,ticket64表还是只有一行数据,只是id字段的值为2。这个表将一直只有一行数据。
更棒的方法:
比如,只需要一张ticket表就可以为所有的业务表提供各自连续的ID。下面,来看一下我们的方法。首先来看一下表结构:
CREATETABLE`sequence`( `name`varchar(50)NOTNULL, `id`bigint(20)unsignedNOTNULLDEFAULT'0', PRIMARYKEY(`name`) )ENGINE=InnoDB;
注意区别,id字段不是自增的,也不是主键。在使用前,我们需要先插入一些初始化数据:
INSERTINTO`sequence`(`name`)VALUES ('users'),('photos'),('albums'),('comments');
接下来,我们可以通过执行下面的SQL语句来获得新的照片ID:
UPDATE`sequence`SET`id`=LAST_INSERT_ID(`id`+1)WHERE`name`='photos'; SELECTLAST_INSERT_ID();
我们执行了一个更新操作,将id字段增加1,并将增加后的值传递到LAST_INSERT_ID函数,从而指定了LAST_INSERT_ID的返回值。
实际上,我们不一定需要预先指定序列的名字。如果我们现在需要一种新的序列,我们可以直接执行下面的SQL语句:
INSERTINTO`sequence`(`name`)VALUES('new_business')ONDUPLICATEKEYUPDATE`id`=LAST_INSERT_ID(`id`+1); SELECTLAST_INSERT_ID();
这里,我们采用了INSERT…ONDUPLICATEKEYUPDATE这个MySQL扩展,这个扩展的功能也和INSERT一样插入一行新的记录,但是当新插入的行的主键或唯一键(UNIQUEKey)和已有的行重复时,会对已有行进行UPDATE操作。
当我们第一次执行上面的语句时,因为还没有name为'new_business'的字段,所以正常的执行了插入操作,需要注意的是通过这种方式获取的序列起始值为0,而不是1。因为第一次执行时,没有执行UPDATE,所以也没有为LAST_INSERT_ID传递值,我们也没有自增字段,所以SELECTLAST_INSERT_ID()将返回0。不过这个应该不是什么大问题。
UPDATE:这个方法更容易解决单点问题,也不局限于两个服务器,只要对不同的服务器设置不同的初始值(但必须是连续的),然后将增量变为服务器数就行了。
以上内容是基于MySql的扩展功能生成全局ID的相关资料,希望大家喜欢。