之前因为时间匆忙,大区里产生唯一ID只是简单写了一个方法,今天趁着有时间,把里面一些过程写出来,也算是个总结。 首先说说需求,现在游戏里数据库为了分散热点,都采用分表方式,以前那种一张表AUTO_INCREMENT的方式显然不行了,那么将唯一ID放到业务进程里可行吗?这个也不好,因为现在后台都是多个部署,每个进程可以保证ID唯一,但是存到数据库的时候就可能重复,所以我们还是得在DB上做文章。 因此就有了上篇文章的解决方案,单独一张表,这张表的作用就是专门产生唯一ID,而且为多个业务提供唯一ID,多进程情况下也不需要锁表,效率比较高,是不是很像设计模式里的工厂。接着我来分析下这张表。我们再来看看表结构和用法
create table SeqTab (
iSeqNo bigint(20) not null default 0, //表示唯一ID
iSeqType int(11) not null default 0, //表示业务ID
primary key(iSeqNo,iSeqType));
insert into SeqTab values(0,1); //初始化,假设一个业务编号为1
update SeqTab set iSeqNo=last_insert_id(iSeqNo+1) where iSeqType=1;
select last_insert_id(); //这两句是获取一个业务的唯一ID,供业务进程使用。 其实说到这张表,关键是说LAST_INSERT_ID()这个方法。它有两种形式LAST_INSERT_ID(),LAST_INSERT_ID(expr)。 这个东西的特点是,1.属于每个CONNECTION,CONNECTION之间相互不会影响 2.不属于某个具体的表 3.返回最后一次INSERT AUTO_INCREMENT的值 4.假如以此使用INSERT插入 多行数据,只返回第一行数据产生的值 5.如果你UPDATE某个AUTO_INCREMENT的值,不会影响LAST_INSERT_ID()返回值 LAST_INSERT_ID(expr)与LAST_INSERT_ID()稍有不同,首先它返回expr的值,其次它的返回值会记录在LAST_INSERT_ID()。 我们这里主要使用到了第一和第二个特点,每个进程并发执行update SeqTab set iSeqNo=last_insert_id(iSeqNo+1) where iSeqType=1;,就获取属于进程自己的iSeqNo并且记录在 LAST_INSERT_ID中,通过第二句取出该值。 接着我们在比较下其他一些办法。 第一种是直接一张表,里面有一个ID字段,设置成AUTO_INCREMENT。这个的问题是每个业务ID不是连续的,是离散的。 第二种是使用GUID或者UUID,但是这个问题我个人觉得是效率上的差异,字符串没有数字的效率好,另外数字ID今后也可以拼接一些区信息,之后跨区的时候可以方便获取对象是哪个区的.
posted on 2012-12-06 23:01
梨树阳光 阅读(2189)
评论(2) 编辑 收藏 引用 所属分类:
数据库